Merge branch 'master' into colorpicker

This commit is contained in:
Joao Moreno
2017-07-26 21:54:00 +02:00
1407 changed files with 26016 additions and 11353 deletions

View File

@@ -35,6 +35,7 @@ import { ExtHostLanguageFeatures } from 'vs/workbench/api/node/extHostLanguageFe
import { ExtHostApiCommands } from 'vs/workbench/api/node/extHostApiCommands';
import { ExtHostTask } from 'vs/workbench/api/node/extHostTask';
import { ExtHostDebugService } from 'vs/workbench/api/node/extHostDebugService';
import { ExtHostCredentials } from 'vs/workbench/api/node/extHostCredentials';
import * as extHostTypes from 'vs/workbench/api/node/extHostTypes';
import URI from 'vs/base/common/uri';
import Severity from 'vs/base/common/severity';
@@ -55,12 +56,6 @@ export interface IExtensionApiFactory {
(extension: IExtensionDescription): typeof vscode;
}
function assertProposedApi(extension: IExtensionDescription): void {
if (!extension.enableProposedApi) {
throw new Error(`[${extension.id}]: Proposed API is only available when running out of dev or with the following command line switch: --enable-proposed-api ${extension.id}`);
}
}
function proposedApiFunction<T>(extension: IExtensionDescription, fn: T): T {
if (extension.enableProposedApi) {
return fn;
@@ -90,7 +85,7 @@ export function createApiFactory(
const extHostDocumentSaveParticipant = col.define(ExtHostContext.ExtHostDocumentSaveParticipant).set<ExtHostDocumentSaveParticipant>(new ExtHostDocumentSaveParticipant(extHostDocuments, threadService.get(MainContext.MainThreadWorkspace)));
const extHostEditors = col.define(ExtHostContext.ExtHostEditors).set<ExtHostEditors>(new ExtHostEditors(threadService, extHostDocumentsAndEditors));
const extHostCommands = col.define(ExtHostContext.ExtHostCommands).set<ExtHostCommands>(new ExtHostCommands(threadService, extHostHeapService));
const extHostTreeViews = col.define(ExtHostContext.ExtHostTreeViews).set<ExtHostTreeViews>(new ExtHostTreeViews(threadService, extHostCommands));
const extHostTreeViews = col.define(ExtHostContext.ExtHostTreeViews).set<ExtHostTreeViews>(new ExtHostTreeViews(threadService.get(MainContext.MainThreadTreeViews), extHostCommands));
const extHostWorkspace = col.define(ExtHostContext.ExtHostWorkspace).set<ExtHostWorkspace>(new ExtHostWorkspace(threadService, initData.workspace));
const extHostConfiguration = col.define(ExtHostContext.ExtHostConfiguration).set<ExtHostConfiguration>(new ExtHostConfiguration(threadService.get(MainContext.MainThreadConfiguration), extHostWorkspace, initData.configuration));
const extHostDiagnostics = col.define(ExtHostContext.ExtHostDiagnostics).set<ExtHostDiagnostics>(new ExtHostDiagnostics(threadService));
@@ -100,6 +95,7 @@ export function createApiFactory(
const extHostTerminalService = col.define(ExtHostContext.ExtHostTerminalService).set<ExtHostTerminalService>(new ExtHostTerminalService(threadService));
const extHostSCM = col.define(ExtHostContext.ExtHostSCM).set<ExtHostSCM>(new ExtHostSCM(threadService, extHostCommands));
const extHostTask = col.define(ExtHostContext.ExtHostTask).set<ExtHostTask>(new ExtHostTask(threadService));
const extHostCredentials = col.define(ExtHostContext.ExtHostCredentials).set<ExtHostCredentials>(new ExtHostCredentials(threadService));
col.define(ExtHostContext.ExtHostExtensionService).set(extensionService);
col.finish(false, threadService);
@@ -131,6 +127,20 @@ export function createApiFactory(
}
}
const apiUsage = new class {
private _seen = new Set<string>();
publicLog(apiName: string) {
if (this._seen.has(apiName)) {
return undefined;
}
this._seen.add(apiName);
return telemetryService.publicLog('apiUsage', {
name: apiName,
extension: extension.id
});
}
};
// namespace: commands
const commands: typeof vscode.commands = {
registerCommand<T>(id: string, command: <T>(...args: any[]) => T | Thenable<T>, thisArgs?: any): vscode.Disposable {
@@ -278,8 +288,16 @@ export function createApiFactory(
get visibleTextEditors() {
return extHostEditors.getVisibleTextEditors();
},
showTextDocument(document: vscode.TextDocument, columnOrOptions?: vscode.ViewColumn | vscode.TextDocumentShowOptions, preserveFocus?: boolean): TPromise<vscode.TextEditor> {
return extHostEditors.showTextDocument(document, columnOrOptions, preserveFocus);
showTextDocument(documentOrUri: vscode.TextDocument | vscode.Uri, columnOrOptions?: vscode.ViewColumn | vscode.TextDocumentShowOptions, preserveFocus?: boolean): TPromise<vscode.TextEditor> {
let documentPromise: TPromise<vscode.TextDocument>;
if (URI.isUri(documentOrUri)) {
documentPromise = TPromise.wrap(workspace.openTextDocument(documentOrUri));
} else {
documentPromise = TPromise.wrap(<vscode.TextDocument>documentOrUri);
}
return documentPromise.then(document => {
return extHostEditors.showTextDocument(document, columnOrOptions, preserveFocus);
});
},
createTextEditorDecorationType(options: vscode.DecorationRenderOptions): vscode.TextEditorDecorationType {
return extHostEditors.createTextEditorDecorationType(options);
@@ -351,30 +369,23 @@ export function createApiFactory(
// namespace: workspace
const workspace: typeof vscode.workspace = {
get rootPath() {
telemetryService.publicLog('api-getter', {
name: 'workspace#rootPath',
extension: extension.id
});
apiUsage.publicLog('workspace#rootPath');
return extHostWorkspace.getPath();
},
set rootPath(value) {
throw errors.readonly();
},
get workspaceFolders() {
assertProposedApi(extension);
telemetryService.publicLog('api-getter', {
name: 'workspace#workspaceFolders',
extension: extension.id
});
return extHostWorkspace.getRoots();
getWorkspaceFolder(resource) {
return extHostWorkspace.getWorkspaceFolder(resource);
},
onDidChangeWorkspaceFolders: proposedApiFunction(extension, (listener, thisArgs?, disposables?) => {
telemetryService.publicLog('api-getter', {
name: 'workspace#onDidChangeWorkspaceFolders',
extension: extension.id
});
get workspaceFolders() {
apiUsage.publicLog('workspace#workspaceFolders');
return extHostWorkspace.getWorkspaceFolders();
},
onDidChangeWorkspaceFolders: function (listener, thisArgs?, disposables?) {
apiUsage.publicLog('workspace#onDidChangeWorkspaceFolders');
return extHostWorkspace.onDidChangeWorkspace(listener, thisArgs, disposables);
}),
},
asRelativePath: (pathOrUri) => {
return extHostWorkspace.getRelativePath(pathOrUri);
},
@@ -446,7 +457,10 @@ export function createApiFactory(
}),
registerTaskProvider: (type: string, provider: vscode.TaskProvider) => {
return extHostTask.registerTaskProvider(extension, provider);
}
},
registerFileSystemProvider: proposedApiFunction(extension, (authority, provider) => {
return extHostWorkspace.registerFileSystemProvider(authority, provider);
})
};
// namespace: scm
@@ -467,12 +481,40 @@ export function createApiFactory(
// namespace: debug
const debug: typeof vscode.debug = {
createDebugSession: proposedApiFunction(extension, (config: vscode.DebugConfiguration) => {
return extHostDebugService.createDebugSession(config);
get activeDebugSession() {
return extHostDebugService.activeDebugSession;
},
startDebugging: proposedApiFunction(extension, (folder: vscode.WorkspaceFolder | undefined, nameOrConfig: string | vscode.DebugConfiguration) => {
return extHostDebugService.startDebugging(folder, nameOrConfig);
}),
onDidTerminateDebugSession: proposedApiFunction(extension, (listener, thisArg?, disposables?) => {
startDebugSession(folder: vscode.WorkspaceFolder | undefined, config: vscode.DebugConfiguration) {
return extHostDebugService.startDebugSession(folder, config);
},
onDidStartDebugSession(listener, thisArg?, disposables?) {
return extHostDebugService.onDidStartDebugSession(listener, thisArg, disposables);
},
onDidTerminateDebugSession(listener, thisArg?, disposables?) {
return extHostDebugService.onDidTerminateDebugSession(listener, thisArg, disposables);
})
},
onDidChangeActiveDebugSession(listener, thisArg?, disposables?) {
return extHostDebugService.onDidChangeActiveDebugSession(listener, thisArg, disposables);
},
onDidReceiveDebugSessionCustomEvent(listener, thisArg?, disposables?) {
return extHostDebugService.onDidReceiveDebugSessionCustomEvent(listener, thisArg, disposables);
}
};
// namespace: credentials
const credentials: typeof vscode.credentials = {
readSecret(service: string, account: string): Thenable<string | undefined> {
return extHostCredentials.readSecret(service, account);
},
writeSecret(service: string, account: string, secret: string): Thenable<void> {
return extHostCredentials.writeSecret(service, account, secret);
},
deleteSecret(service: string, account: string): Thenable<boolean> {
return extHostCredentials.deleteSecret(service, account);
}
};
@@ -487,6 +529,11 @@ export function createApiFactory(
workspace,
scm,
debug,
get credentials() {
return proposedApiFunction(extension, () => {
return credentials;
})();
},
// types
CancellationTokenSource: CancellationTokenSource,
CodeLens: extHostTypes.CodeLens,
@@ -524,7 +571,7 @@ export function createApiFactory(
TextEditorRevealType: extHostTypes.TextEditorRevealType,
TextEditorSelectionChangeKind: extHostTypes.TextEditorSelectionChangeKind,
DecorationRangeBehavior: extHostTypes.DecorationRangeBehavior,
Uri: URI,
Uri: <any>URI,
ViewColumn: extHostTypes.ViewColumn,
WorkspaceEdit: extHostTypes.WorkspaceEdit,
ProgressLocation: extHostTypes.ProgressLocation,

View File

@@ -183,6 +183,7 @@ export interface ITextDocumentShowOptions {
position?: EditorPosition;
preserveFocus?: boolean;
pinned?: boolean;
selection?: IRange;
}
export abstract class MainThreadEditorsShape {
@@ -202,7 +203,7 @@ export abstract class MainThreadEditorsShape {
export abstract class MainThreadTreeViewsShape {
$registerView(treeViewId: string): void { throw ni(); }
$refresh(treeViewId: string, treeItemHandle?: number): void { throw ni(); }
$refresh(treeViewId: string, treeItemHandles: number[]): void { throw ni(); }
}
export abstract class MainThreadErrorsShape {
@@ -262,7 +263,6 @@ export abstract class MainThreadTerminalServiceShape {
$hide(terminalId: number): void { throw ni(); }
$sendText(terminalId: number, text: string, addNewLine: boolean): void { throw ni(); }
$show(terminalId: number, preserveFocus: boolean): void { throw ni(); }
$registerOnData(terminalId: number): void { throw ni(); }
}
export interface MyQuickPickItems extends IPickOpenEntry {
@@ -295,6 +295,8 @@ export abstract class MainThreadWorkspaceShape {
$cancelSearch(requestId: number): Thenable<boolean> { throw ni(); }
$saveAll(includeUntitled?: boolean): Thenable<boolean> { throw ni(); }
$applyWorkspaceEdit(edits: IResourceEdit[]): TPromise<boolean> { throw ni(); }
$registerFileSystemProvider(handle: number, authority: string): void { throw ni(); }
$onFileSystemChange(handle: number, resource: URI): void { throw ni(); }
}
export abstract class MainThreadTaskShape {
@@ -346,10 +348,17 @@ export abstract class MainThreadSCMShape {
export type DebugSessionUUID = string;
export abstract class MainThreadDebugServiceShape {
$createDebugSession(config: vscode.DebugConfiguration): TPromise<DebugSessionUUID> { throw ni(); }
$startDebugging(folderUri: URI | undefined, nameOrConfig: string | vscode.DebugConfiguration): TPromise<boolean> { throw ni(); }
$startDebugSession(folderUri: URI | undefined, config: vscode.DebugConfiguration): TPromise<DebugSessionUUID> { throw ni(); }
$customDebugAdapterRequest(id: DebugSessionUUID, command: string, args: any): TPromise<any> { throw ni(); }
}
export abstract class MainThreadCredentialsShape {
$readSecret(service: string, account: string): Thenable<string | undefined> { throw ni(); }
$writeSecret(service: string, account: string, secret: string): Thenable<void> { throw ni(); }
$deleteSecret(service: string, account: string): Thenable<boolean> { throw ni(); }
}
// -- extension host
export abstract class ExtHostCommandsShape {
@@ -420,6 +429,8 @@ export abstract class ExtHostTreeViewsShape {
export abstract class ExtHostWorkspaceShape {
$acceptWorkspaceData(workspace: IWorkspaceData): void { throw ni(); }
$resolveFile(handle: number, resource: URI): TPromise<string> { throw ni(); }
$storeFile(handle: number, resource: URI, content: string): TPromise<any> { throw ni(); }
}
export abstract class ExtHostExtensionServiceShape {
@@ -470,7 +481,7 @@ export abstract class ExtHostLanguageFeaturesShape {
$provideHover(handle: number, resource: URI, position: IPosition): TPromise<modes.Hover> { throw ni(); }
$provideDocumentHighlights(handle: number, resource: URI, position: IPosition): TPromise<modes.DocumentHighlight[]> { throw ni(); }
$provideReferences(handle: number, resource: URI, position: IPosition, context: modes.ReferenceContext): TPromise<modes.Location[]> { throw ni(); }
$provideCodeActions(handle: number, resource: URI, range: IRange): TPromise<modes.CodeAction[]> { throw ni(); }
$provideCodeActions(handle: number, resource: URI, range: IRange): TPromise<modes.Command[]> { throw ni(); }
$provideDocumentFormattingEdits(handle: number, resource: URI, options: modes.FormattingOptions): TPromise<editorCommon.ISingleEditOperation[]> { throw ni(); }
$provideDocumentRangeFormattingEdits(handle: number, resource: URI, range: IRange, options: modes.FormattingOptions): TPromise<editorCommon.ISingleEditOperation[]> { throw ni(); }
$provideOnTypeFormattingEdits(handle: number, resource: URI, position: IPosition, ch: string, options: modes.FormattingOptions): TPromise<editorCommon.ISingleEditOperation[]> { throw ni(); }
@@ -493,7 +504,6 @@ export abstract class ExtHostQuickOpenShape {
export abstract class ExtHostTerminalServiceShape {
$acceptTerminalClosed(id: number): void { throw ni(); }
$acceptTerminalProcessId(id: number, processId: number): void { throw ni(); }
$acceptTerminalData(id: number, data: string): void { throw ni(); }
}
export abstract class ExtHostSCMShape {
@@ -508,7 +518,13 @@ export abstract class ExtHostTaskShape {
}
export abstract class ExtHostDebugServiceShape {
$acceptDebugSessionStarted(id: DebugSessionUUID, type: string, name: string): void { throw ni(); }
$acceptDebugSessionTerminated(id: DebugSessionUUID, type: string, name: string): void { throw ni(); }
$acceptDebugSessionActiveChanged(id: DebugSessionUUID | undefined, type?: string, name?: string): void { throw ni(); }
$acceptDebugSessionCustomEvent(id: DebugSessionUUID, type: string, name: string, event: any): void { throw ni(); }
}
export abstract class ExtHostCredentialsShape {
}
// --- proxy identifiers
@@ -535,7 +551,8 @@ export const MainContext = {
MainThreadWorkspace: createMainId<MainThreadWorkspaceShape>('MainThreadWorkspace', MainThreadWorkspaceShape),
MainProcessExtensionService: createMainId<MainProcessExtensionServiceShape>('MainProcessExtensionService', MainProcessExtensionServiceShape),
MainThreadSCM: createMainId<MainThreadSCMShape>('MainThreadSCM', MainThreadSCMShape),
MainThreadTask: createMainId<MainThreadTaskShape>('MainThreadTask', MainThreadTaskShape)
MainThreadTask: createMainId<MainThreadTaskShape>('MainThreadTask', MainThreadTaskShape),
MainThreadCredentials: createMainId<MainThreadCredentialsShape>('MainThreadCredentials', MainThreadCredentialsShape),
};
export const ExtHostContext = {
@@ -557,4 +574,5 @@ export const ExtHostContext = {
ExtHostSCM: createExtId<ExtHostSCMShape>('ExtHostSCM', ExtHostSCMShape),
ExtHostTask: createExtId<ExtHostTaskShape>('ExtHostTask', ExtHostTaskShape),
ExtHostWorkspace: createExtId<ExtHostWorkspaceShape>('ExtHostWorkspace', ExtHostWorkspaceShape),
ExtHostCredentials: createExtId<ExtHostCredentialsShape>('ExtHostCredentials', ExtHostCredentialsShape),
};

View File

@@ -15,7 +15,7 @@ import * as modes from 'vs/editor/common/modes';
import { ICommandHandlerDescription } from 'vs/platform/commands/common/commands';
import { ExtHostCommands } from 'vs/workbench/api/node/extHostCommands';
import { IWorkspaceSymbolProvider } from 'vs/workbench/parts/search/common/search';
import { IEditorOptions } from 'vs/platform/editor/common/editor';
import { ITextEditorOptions } from 'vs/platform/editor/common/editor';
export class ExtHostApiCommands {
@@ -205,12 +205,12 @@ export class ExtHostApiCommands {
});
this._register('vscode.diff', (left: URI, right: URI, label: string, options?: vscode.TextDocumentShowOptions) => {
let editorOptions: IEditorOptions;
let editorOptions: ITextEditorOptions;
if (options) {
editorOptions = {
pinned: !options.preview,
preserveFocus: options.preserveFocus
pinned: typeof options.preview === 'boolean' ? !options.preview : undefined,
preserveFocus: options.preserveFocus,
selection: typeof options.selection === 'object' ? typeConverters.fromRange(options.selection) : undefined
};
}
@@ -234,7 +234,7 @@ export class ExtHostApiCommands {
this._register('vscode.open', (resource: URI, column: vscode.ViewColumn) => {
return this._commands.executeCommand('_workbench.open', [resource, typeConverters.fromViewColumn(column)]);
}, {
description: 'Opens the provided resource in the editor. Can be a text or binary file, or a http(s) url',
description: 'Opens the provided resource in the editor. Can be a text or binary file, or a http(s) url. If you need more control over the options for opening a text file, use vscode.window.showTextDocument instead.',
args: [
{ name: 'resource', description: 'Resource to open', constraint: URI },
{ name: 'column', description: '(optional) Column in which to open', constraint: v => v === void 0 || typeof v === 'number' }
@@ -399,11 +399,11 @@ export class ExtHostApiCommands {
resource,
range: typeConverters.fromRange(range)
};
return this._commands.executeCommand<modes.CodeAction[]>('_executeCodeActionProvider', args).then(value => {
return this._commands.executeCommand<modes.Command[]>('_executeCodeActionProvider', args).then(value => {
if (!Array.isArray(value)) {
return undefined;
}
return value.map(quickFix => this._commands.converter.fromInternal(quickFix.command));
return value.map(quickFix => this._commands.converter.fromInternal(quickFix));
});
}

View File

@@ -0,0 +1,31 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import { MainContext, MainThreadCredentialsShape, ExtHostCredentialsShape } from 'vs/workbench/api/node/extHost.protocol';
import { IThreadService } from 'vs/workbench/services/thread/common/threadService';
export class ExtHostCredentials extends ExtHostCredentialsShape {
private _proxy: MainThreadCredentialsShape;
constructor(threadService: IThreadService) {
super();
this._proxy = threadService.get(MainContext.MainThreadCredentials);
};
readSecret(service: string, account: string): Thenable<string | undefined> {
return this._proxy.$readSecret(service, account);
}
writeSecret(service: string, account: string, secret: string): Thenable<void> {
return this._proxy.$writeSecret(service, account, secret);
}
deleteSecret(service: string, account: string): Thenable<boolean> {
return this._proxy.$deleteSecret(service, account);
}
}

View File

@@ -11,6 +11,7 @@ import { IThreadService } from 'vs/workbench/services/thread/common/threadServic
import { MainContext, MainThreadDebugServiceShape, ExtHostDebugServiceShape, DebugSessionUUID } from 'vs/workbench/api/node/extHost.protocol';
import * as vscode from 'vscode';
import URI from 'vs/base/common/uri';
export class ExtHostDebugService extends ExtHostDebugServiceShape {
@@ -18,35 +19,96 @@ export class ExtHostDebugService extends ExtHostDebugServiceShape {
private _debugServiceProxy: MainThreadDebugServiceShape;
private _debugSessions: Map<DebugSessionUUID, ExtHostDebugSession> = new Map<DebugSessionUUID, ExtHostDebugSession>();
private _onDidStartDebugSession: Emitter<vscode.DebugSession>;
get onDidStartDebugSession(): Event<vscode.DebugSession> { return this._onDidStartDebugSession.event; }
private _onDidTerminateDebugSession: Emitter<vscode.DebugSession>;
get onDidTerminateDebugSession(): Event<vscode.DebugSession> { return this._onDidTerminateDebugSession.event; }
private _onDidChangeActiveDebugSession: Emitter<vscode.DebugSession | undefined>;
get onDidChangeActiveDebugSession(): Event<vscode.DebugSession | undefined> { return this._onDidChangeActiveDebugSession.event; }
private _activeDebugSession: ExtHostDebugSession | undefined;
get activeDebugSession(): ExtHostDebugSession | undefined { return this._activeDebugSession; }
private _onDidReceiveDebugSessionCustomEvent: Emitter<vscode.DebugSessionCustomEvent>;
get onDidReceiveDebugSessionCustomEvent(): Event<vscode.DebugSessionCustomEvent> { return this._onDidReceiveDebugSessionCustomEvent.event; }
constructor(threadService: IThreadService) {
super();
this._onDidStartDebugSession = new Emitter<vscode.DebugSession>();
this._onDidTerminateDebugSession = new Emitter<vscode.DebugSession>();
this._onDidChangeActiveDebugSession = new Emitter<vscode.DebugSession>();
this._onDidReceiveDebugSessionCustomEvent = new Emitter<vscode.DebugSessionCustomEvent>();
this._debugServiceProxy = threadService.get(MainContext.MainThreadDebugService);
}
public createDebugSession(config: vscode.DebugConfiguration): TPromise<vscode.DebugSession> {
public startDebugging(folder: vscode.WorkspaceFolder | undefined, nameOrConfig: string | vscode.DebugConfiguration): TPromise<boolean> {
return this._debugServiceProxy.$createDebugSession(config).then((id: DebugSessionUUID) => {
return this._debugServiceProxy.$startDebugging(folder ? <URI>folder.uri : undefined, nameOrConfig);
}
public startDebugSession(folder: vscode.WorkspaceFolder | undefined, config: vscode.DebugConfiguration): TPromise<vscode.DebugSession> {
return this._debugServiceProxy.$startDebugSession(folder ? <URI>folder.uri : undefined, config).then((id: DebugSessionUUID) => {
const debugSession = new ExtHostDebugSession(this._debugServiceProxy, id, config.type, config.name);
this._debugSessions.set(id, debugSession);
return debugSession;
});
}
public $acceptDebugSessionStarted(id: DebugSessionUUID, type: string, name: string): void {
let debugSession = this._debugSessions.get(id);
if (!debugSession) {
debugSession = new ExtHostDebugSession(this._debugServiceProxy, id, type, name);
this._debugSessions.set(id, debugSession);
}
this._onDidStartDebugSession.fire(debugSession);
}
public $acceptDebugSessionTerminated(id: DebugSessionUUID, type: string, name: string): void {
let debugSession = this._debugSessions.get(id);
if (!debugSession) {
debugSession = new ExtHostDebugSession(this._debugServiceProxy, id, type, name);
this._debugSessions.set(id, debugSession);
}
this._onDidTerminateDebugSession.fire(debugSession);
this._debugSessions.delete(id);
}
public $acceptDebugSessionActiveChanged(id: DebugSessionUUID | undefined, type?: string, name?: string): void {
if (id) {
this._activeDebugSession = this._debugSessions.get(id);
if (!this._activeDebugSession) {
this._activeDebugSession = new ExtHostDebugSession(this._debugServiceProxy, id, type, name);
this._debugSessions.set(id, this._activeDebugSession);
}
} else {
this._activeDebugSession = undefined;
}
this._onDidChangeActiveDebugSession.fire(this._activeDebugSession);
}
public $acceptDebugSessionCustomEvent(id: DebugSessionUUID, type: string, name: string, event: any): void {
let debugSession = this._debugSessions.get(id);
if (!debugSession) {
debugSession = new ExtHostDebugSession(this._debugServiceProxy, id, type, name);
this._debugSessions.set(id, debugSession);
}
const ee: vscode.DebugSessionCustomEvent = {
session: debugSession,
event: event.event,
body: event.body
};
this._onDidReceiveDebugSessionCustomEvent.fire(ee);
}
}
export class ExtHostDebugSession implements vscode.DebugSession {
@@ -58,7 +120,6 @@ export class ExtHostDebugSession implements vscode.DebugSession {
private _type: string;
private _name: string;
constructor(proxy: MainThreadDebugServiceShape, id: DebugSessionUUID, type: string, name: string) {
this._debugServiceProxy = proxy;
this._id = id;
@@ -66,6 +127,10 @@ export class ExtHostDebugSession implements vscode.DebugSession {
this._name = name;
};
public get id(): string {
return this._id;
}
public get type(): string {
return this._type;
}

View File

@@ -271,7 +271,7 @@ class QuickFixAdapter {
this._provider = provider;
}
provideCodeActions(resource: URI, range: IRange): TPromise<modes.CodeAction[]> {
provideCodeActions(resource: URI, range: IRange): TPromise<modes.Command[]> {
const doc = this._documents.getDocumentData(resource).document;
const ran = TypeConverters.toRange(range);
@@ -291,12 +291,7 @@ class QuickFixAdapter {
if (!Array.isArray(commands)) {
return undefined;
}
return commands.map((command, i) => {
return <modes.CodeAction>{
command: this._commands.toInternal(command),
score: i
};
});
return commands.map(command => this._commands.toInternal(command));
});
}
}
@@ -735,7 +730,7 @@ export class ExtHostLanguageFeatures extends ExtHostLanguageFeaturesShape {
return ExtHostLanguageFeatures._handlePool++;
}
private _withAdapter<A, R>(handle: number, ctor: { new (...args: any[]): A }, callback: (adapter: A) => TPromise<R>): TPromise<R> {
private _withAdapter<A, R>(handle: number, ctor: { new(...args: any[]): A }, callback: (adapter: A) => TPromise<R>): TPromise<R> {
let adapter = this._adapter.get(handle);
if (!(adapter instanceof ctor)) {
return TPromise.wrapError<R>(new Error('no adapter found'));
@@ -865,7 +860,7 @@ export class ExtHostLanguageFeatures extends ExtHostLanguageFeaturesShape {
return this._createDisposable(handle);
}
$provideCodeActions(handle: number, resource: URI, range: IRange): TPromise<modes.CodeAction[]> {
$provideCodeActions(handle: number, resource: URI, range: IRange): TPromise<modes.Command[]> {
return this._withAdapter(handle, QuickFixAdapter, adapter => adapter.provideCodeActions(resource, range));
}

View File

@@ -352,7 +352,8 @@ namespace Tasks {
group: task.group ? (task.group as types.TaskGroup).id : undefined,
command: command,
isBackground: !!task.isBackground,
problemMatchers: task.problemMatchers.slice()
problemMatchers: task.problemMatchers.slice(),
hasDefinedMatchers: (task as types.Task).hasDefinedMatchers
};
return result;
}

View File

@@ -20,8 +20,6 @@ export class ExtHostTerminal implements vscode.Terminal {
private _pidPromise: TPromise<number>;
private _pidPromiseComplete: TValueCallback<number>;
private _onDataCallback: (data: string) => any;
constructor(
proxy: MainThreadTerminalServiceShape,
name?: string,
@@ -69,11 +67,6 @@ export class ExtHostTerminal implements vscode.Terminal {
this._queueApiRequest(this._proxy.$hide, []);
}
public onData(callback: (data: string) => any): void {
this._onDataCallback = callback;
this._queueApiRequest(this._proxy.$registerOnData, []);
}
public dispose(): void {
if (!this._disposed) {
this._disposed = true;
@@ -86,10 +79,6 @@ export class ExtHostTerminal implements vscode.Terminal {
this._pidPromiseComplete = null;
}
public _onData(data: string): void {
this._onDataCallback(data);
}
private _queueApiRequest(callback: (...args: any[]) => void, args: any[]) {
let request: ApiRequest = new ApiRequest(callback, args);
if (!this._id) {
@@ -149,11 +138,6 @@ export class ExtHostTerminalService implements ExtHostTerminalServiceShape {
terminal._setProcessId(processId);
}
public $acceptTerminalData(id: number, data: string): void {
let terminal = this._getTerminalById(id);
terminal._onData(data);
}
private _getTerminalById(id: number): ExtHostTerminal {
let index = this._getTerminalIndexById(id);
return index !== null ? this._terminals[index] : null;

View File

@@ -63,20 +63,19 @@ export class ExtHostEditors extends ExtHostEditorsShape {
if (typeof columnOrOptions === 'number') {
options = {
position: TypeConverters.fromViewColumn(columnOrOptions),
preserveFocus: preserveFocus,
pinned: true
preserveFocus
};
} else if (typeof columnOrOptions === 'object') {
options = {
position: TypeConverters.fromViewColumn(columnOrOptions.viewColumn),
preserveFocus: columnOrOptions.preserveFocus,
pinned: columnOrOptions.preview === undefined ? true : !columnOrOptions.preview
selection: typeof columnOrOptions.selection === 'object' ? TypeConverters.fromRange(columnOrOptions.selection) : undefined,
pinned: typeof columnOrOptions.preview === 'boolean' ? !columnOrOptions.preview : undefined
};
} else {
options = {
position: EditorPosition.ONE,
preserveFocus: false,
pinned: true
preserveFocus: false
};
}

View File

@@ -7,10 +7,11 @@
import { localize } from 'vs/nls';
import * as vscode from 'vscode';
import URI from 'vs/base/common/uri';
import { distinct } from 'vs/base/common/arrays';
import { debounceEvent } from 'vs/base/common/event';
import { TPromise } from 'vs/base/common/winjs.base';
import { Disposable } from 'vs/base/common/lifecycle';
import { IThreadService } from 'vs/workbench/services/thread/common/threadService';
import { MainContext, ExtHostTreeViewsShape, MainThreadTreeViewsShape } from './extHost.protocol';
import { ExtHostTreeViewsShape, MainThreadTreeViewsShape } from './extHost.protocol';
import { ITreeItem, TreeViewItemHandleArg } from 'vs/workbench/parts/views/common/views';
import { TreeItemCollapsibleState } from './extHostTypes';
import { ExtHostCommands, CommandsConverter } from 'vs/workbench/api/node/extHostCommands';
@@ -21,14 +22,12 @@ type TreeItemHandle = number;
export class ExtHostTreeViews extends ExtHostTreeViewsShape {
private treeViews: Map<string, ExtHostTreeView<any>> = new Map<string, ExtHostTreeView<any>>();
private _proxy: MainThreadTreeViewsShape;
constructor(
threadService: IThreadService,
private _proxy: MainThreadTreeViewsShape,
private commands: ExtHostCommands
) {
super();
this._proxy = threadService.get(MainContext.MainThreadTreeViews);
commands.registerArgumentProcessor({
processArgument: arg => {
if (arg && arg.$treeViewId && arg.$treeItemHandle) {
@@ -80,11 +79,11 @@ class ExtHostTreeView<T> extends Disposable {
private itemHandlesMap: Map<T, TreeItemHandle> = new Map<T, TreeItemHandle>();
private extChildrenElementsMap: Map<T, T[]> = new Map<T, T[]>();
constructor(private viewId: string, private dataProvider: vscode.TreeDataProvider<T>, private proxy: MainThreadTreeViewsShape, private commands: CommandsConverter, ) {
constructor(private viewId: string, private dataProvider: vscode.TreeDataProvider<T>, private proxy: MainThreadTreeViewsShape, private commands: CommandsConverter) {
super();
this.proxy.$registerView(viewId);
if (dataProvider.onDidChangeTreeData) {
this._register(dataProvider.onDidChangeTreeData(element => this._refresh(element)));
this._register(debounceEvent<T, T[]>(dataProvider.onDidChangeTreeData, (last, current) => last ? [...last, current] : [current], 200)(elements => this._refresh(elements)));
}
}
@@ -113,14 +112,16 @@ class ExtHostTreeView<T> extends Disposable {
return this.extElementsMap.get(treeItemHandle);
}
private _refresh(element: T): void {
if (element) {
const itemHandle = this.itemHandlesMap.get(element);
if (itemHandle) {
this.proxy.$refresh(this.viewId, itemHandle);
}
private _refresh(elements: T[]): void {
const hasRoot = elements.some(element => !element);
if (hasRoot) {
this.proxy.$refresh(this.viewId, []);
} else {
this.proxy.$refresh(this.viewId);
const itemHandles = distinct(elements.map(element => this.itemHandlesMap.get(element))
.filter(itemHandle => !!itemHandle));
if (itemHandles.length) {
this.proxy.$refresh(this.viewId, itemHandles);
}
}
}

View File

@@ -489,14 +489,12 @@ export class TextEdit {
}
}
export class Uri extends URI { }
export class WorkspaceEdit {
private _values: [Uri, TextEdit[]][] = [];
private _values: [URI, TextEdit[]][] = [];
private _index = new Map<string, number>();
replace(uri: Uri, range: Range, newText: string): void {
replace(uri: URI, range: Range, newText: string): void {
let edit = new TextEdit(range, newText);
let array = this.get(uri);
if (array) {
@@ -506,19 +504,19 @@ export class WorkspaceEdit {
}
}
insert(resource: Uri, position: Position, newText: string): void {
insert(resource: URI, position: Position, newText: string): void {
this.replace(resource, new Range(position, position), newText);
}
delete(resource: Uri, range: Range): void {
delete(resource: URI, range: Range): void {
this.replace(resource, range, '');
}
has(uri: Uri): boolean {
has(uri: URI): boolean {
return this._index.has(uri.toString());
}
set(uri: Uri, edits: TextEdit[]): void {
set(uri: URI, edits: TextEdit[]): void {
const idx = this._index.get(uri.toString());
if (typeof idx === 'undefined') {
let newLen = this._values.push([uri, edits]);
@@ -528,12 +526,12 @@ export class WorkspaceEdit {
}
}
get(uri: Uri): TextEdit[] {
get(uri: URI): TextEdit[] {
let idx = this._index.get(uri.toString());
return typeof idx !== 'undefined' && this._values[idx][1];
}
entries(): [Uri, TextEdit[]][] {
entries(): [URI, TextEdit[]][] {
return this._values;
}
@@ -1101,7 +1099,7 @@ export class TaskGroup implements vscode.TaskGroup {
public static Rebuild: TaskGroup = new TaskGroup('rebuild', 'Rebuild');
public static Test: TaskGroup = new TaskGroup('clean', 'Clean');
public static Test: TaskGroup = new TaskGroup('test', 'Test');
constructor(id: string, label: string) {
if (typeof id !== 'string') {
@@ -1217,6 +1215,7 @@ export class Task implements vscode.Task {
private _name: string;
private _execution: ProcessExecution | ShellExecution;
private _problemMatchers: string[];
private _hasDefinedMatchers: boolean;
private _isBackground: boolean;
private _source: string;
private _group: TaskGroup;
@@ -1229,10 +1228,13 @@ export class Task implements vscode.Task {
this.execution = execution;
if (typeof problemMatchers === 'string') {
this._problemMatchers = [problemMatchers];
this._hasDefinedMatchers = true;
} else if (Array.isArray(problemMatchers)) {
this._problemMatchers = problemMatchers;
this._hasDefinedMatchers = true;
} else {
this._problemMatchers = [];
this._hasDefinedMatchers = false;
}
this._isBackground = false;
}
@@ -1286,9 +1288,16 @@ export class Task implements vscode.Task {
set problemMatchers(value: string[]) {
if (!Array.isArray(value)) {
value = [];
this._problemMatchers = [];
this._hasDefinedMatchers = false;
return;
}
this._problemMatchers = value;
this._hasDefinedMatchers = true;
}
get hasDefinedMatchers(): boolean {
return this._hasDefinedMatchers;
}
get isBackground(): boolean {
@@ -1345,7 +1354,7 @@ export enum ProgressLocation {
export class TreeItem {
iconPath?: string | Uri | { light: string | Uri; dark: string | Uri };
iconPath?: string | URI | { light: string | URI; dark: string | URI };
command?: vscode.Command;
contextValue?: string;
@@ -1365,4 +1374,4 @@ export class ThemeColor {
constructor(id: string) {
this.id = id;
}
}
}

View File

@@ -7,8 +7,8 @@
import URI from 'vs/base/common/uri';
import Event, { Emitter } from 'vs/base/common/event';
import { normalize } from 'vs/base/common/paths';
import { isFalsyOrEmpty, delta } from 'vs/base/common/arrays';
import { relative } from 'path';
import { delta } from 'vs/base/common/arrays';
import { relative, basename } from 'path';
import { Workspace } from 'vs/platform/workspace/common/workspace';
import { IThreadService } from 'vs/workbench/services/thread/common/threadService';
import { IResourceEdit } from 'vs/editor/common/services/bulkEdit';
@@ -17,6 +17,54 @@ import { fromRange, EndOfLine } from 'vs/workbench/api/node/extHostTypeConverter
import { IWorkspaceData, ExtHostWorkspaceShape, MainContext, MainThreadWorkspaceShape } from './extHost.protocol';
import * as vscode from 'vscode';
import { compare } from "vs/base/common/strings";
import { asWinJsPromise } from 'vs/base/common/async';
import { Disposable } from 'vs/workbench/api/node/extHostTypes';
import { TrieMap } from 'vs/base/common/map';
class Workspace2 extends Workspace {
static fromData(data: IWorkspaceData) {
return data ? new Workspace2(data) : null;
}
private readonly _folder: vscode.WorkspaceFolder[] = [];
private readonly _structure = new TrieMap<vscode.WorkspaceFolder>(s => s.split('/'));
private constructor(data: IWorkspaceData) {
super(data.id, data.name, data.roots);
// setup the workspace folder data structure
this.roots.forEach((uri, index) => {
const folder = {
name: basename(uri.fsPath),
uri,
index
};
this._folder.push(folder);
this._structure.insert(folder.uri.toString(), folder);
});
}
get folders(): vscode.WorkspaceFolder[] {
return this._folder.slice(0);
}
getWorkspaceFolder(uri: URI): vscode.WorkspaceFolder {
let str = uri.toString();
let folder = this._structure.lookUp(str);
if (folder) {
// `uri` is a workspace folder so we
let parts = str.split('/');
while (parts.length) {
if (parts.pop()) {
break;
}
}
str = parts.join('/');
}
return this._structure.findSubstr(str);
}
}
export class ExtHostWorkspace extends ExtHostWorkspaceShape {
@@ -24,14 +72,14 @@ export class ExtHostWorkspace extends ExtHostWorkspaceShape {
private readonly _onDidChangeWorkspace = new Emitter<vscode.WorkspaceFoldersChangeEvent>();
private readonly _proxy: MainThreadWorkspaceShape;
private _workspace: Workspace;
private _workspace: Workspace2;
readonly onDidChangeWorkspace: Event<vscode.WorkspaceFoldersChangeEvent> = this._onDidChangeWorkspace.event;
constructor(threadService: IThreadService, data: IWorkspaceData) {
super();
this._proxy = threadService.get(MainContext.MainThreadWorkspace);
this._workspace = data ? new Workspace(data.id, data.name, data.roots) : null;
this._workspace = Workspace2.fromData(data);
}
// --- workspace ---
@@ -40,14 +88,21 @@ export class ExtHostWorkspace extends ExtHostWorkspaceShape {
return this._workspace;
}
getRoots(): URI[] {
getWorkspaceFolders(): vscode.WorkspaceFolder[] {
if (!this._workspace) {
return undefined;
} else {
return this._workspace.roots.slice(0);
return this._workspace.folders.slice(0);
}
}
getWorkspaceFolder(uri: vscode.Uri): vscode.WorkspaceFolder {
if (!this._workspace) {
return undefined;
}
return this._workspace.getWorkspaceFolder(<URI>uri);
}
getPath(): string {
// this is legacy from the days before having
// multi-root and we keep it only alive if there
@@ -59,12 +114,7 @@ export class ExtHostWorkspace extends ExtHostWorkspaceShape {
if (roots.length === 0) {
return undefined;
}
// if (roots.length === 1) {
return roots[0].fsPath;
// }
// return `undefined` when there no or more than 1
// root folder.
// return undefined;
}
getRelativePath(pathOrUri: string | vscode.Uri): string {
@@ -80,40 +130,41 @@ export class ExtHostWorkspace extends ExtHostWorkspaceShape {
return path;
}
if (!this._workspace || isFalsyOrEmpty(this._workspace.roots)) {
const folder = this.getWorkspaceFolder(typeof pathOrUri === 'string'
? URI.file(pathOrUri)
: pathOrUri
);
if (!folder) {
return normalize(path);
}
for (const { fsPath } of this._workspace.roots) {
let result = relative(fsPath, path);
if (!result || result.indexOf('..') === 0) {
continue;
}
return normalize(result);
let result = relative(folder.uri.fsPath, path);
if (this.workspace.roots.length > 1) {
result = `${folder.name}/${result}`;
}
return normalize(path);
return normalize(result);
}
$acceptWorkspaceData(data: IWorkspaceData): void {
// compute delta
const oldRoots = this._workspace ? this._workspace.roots.sort(ExtHostWorkspace._compareUri) : [];
const newRoots = data ? data.roots.sort(ExtHostWorkspace._compareUri) : [];
const { added, removed } = delta(oldRoots, newRoots, ExtHostWorkspace._compareUri);
// keep old workspace folder, build new workspace, and
// capture new workspace folders. Compute delta between
// them send that as event
const oldRoots = this._workspace ? this._workspace.folders.sort(ExtHostWorkspace._compareWorkspaceFolder) : [];
// update state
this._workspace = data ? new Workspace(data.id, data.name, data.roots) : null;
this._workspace = Workspace2.fromData(data);
const newRoots = this._workspace ? this._workspace.folders.sort(ExtHostWorkspace._compareWorkspaceFolder) : [];
// send event
const { added, removed } = delta(oldRoots, newRoots, ExtHostWorkspace._compareWorkspaceFolder);
this._onDidChangeWorkspace.fire(Object.freeze({
addedFolders: Object.freeze<vscode.Uri[]>(added),
removedFolders: Object.freeze<vscode.Uri[]>(removed)
added: Object.freeze<vscode.WorkspaceFolder[]>(added),
removed: Object.freeze<vscode.WorkspaceFolder[]>(removed)
}));
}
private static _compareUri(a: vscode.Uri, b: vscode.Uri): number {
return compare(a.toString(), b.toString());
private static _compareWorkspaceFolder(a: vscode.WorkspaceFolder, b: vscode.WorkspaceFolder): number {
return compare(a.uri.toString(), b.uri.toString());
}
// --- search ---
@@ -151,4 +202,30 @@ export class ExtHostWorkspace extends ExtHostWorkspaceShape {
return this._proxy.$applyWorkspaceEdit(resourceEdits);
}
// --- EXPERIMENT: workspace resolver
private readonly _provider = new Map<number, vscode.FileSystemProvider>();
public registerFileSystemProvider(authority: string, provider: vscode.FileSystemProvider): vscode.Disposable {
const handle = this._provider.size;
this._provider.set(handle, provider);
const reg = provider.onDidChange(e => this._proxy.$onFileSystemChange(handle, <URI>e));
this._proxy.$registerFileSystemProvider(handle, authority);
return new Disposable(() => {
this._provider.delete(handle);
reg.dispose();
});
}
$resolveFile(handle: number, resource: URI): TPromise<string> {
const provider = this._provider.get(handle);
return asWinJsPromise(token => provider.resolveContents(resource));
}
$storeFile(handle: number, resource: URI, content: string): TPromise<any> {
const provider = this._provider.get(handle);
return asWinJsPromise(token => provider.writeContents(resource, content));
}
}