Merge branch 'master' into api-window-focus

This commit is contained in:
Joao
2017-08-28 11:11:22 +02:00
1233 changed files with 32502 additions and 17199 deletions

View File

@@ -8,13 +8,13 @@ import { Emitter } from 'vs/base/common/event';
import { TrieMap } from 'vs/base/common/map';
import { score } from 'vs/editor/common/modes/languageSelector';
import * as Platform from 'vs/base/common/platform';
import { IThreadService } from 'vs/workbench/services/thread/common/threadService';
import * as errors from 'vs/base/common/errors';
import product from 'vs/platform/node/product';
import pkg from 'vs/platform/node/package';
import { ExtHostFileSystemEventService } from 'vs/workbench/api/node/extHostFileSystemEventService';
import { ExtHostDocumentsAndEditors } from 'vs/workbench/api/node/extHostDocumentsAndEditors';
import { ExtHostDocuments } from 'vs/workbench/api/node/extHostDocuments';
import { ExtHostDocumentContentProvider } from 'vs/workbench/api/node/extHostDocumentContentProviders';
import { ExtHostDocumentSaveParticipant } from 'vs/workbench/api/node/extHostDocumentSaveParticipant';
import { ExtHostConfiguration } from 'vs/workbench/api/node/extHostConfiguration';
import { ExtHostDiagnostics } from 'vs/workbench/api/node/extHostDiagnostics';
@@ -44,14 +44,16 @@ import EditorCommon = require('vs/editor/common/editorCommon');
import { IExtensionDescription } from 'vs/platform/extensions/common/extensions';
import { ExtHostExtensionService } from 'vs/workbench/api/node/extHostExtensionService';
import { TPromise } from 'vs/base/common/winjs.base';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { CancellationTokenSource } from 'vs/base/common/cancellation';
import * as vscode from 'vscode';
import * as paths from 'vs/base/common/paths';
import { realpath } from 'fs';
import { MainContext, ExtHostContext, InstanceCollection, IInitData } from './extHost.protocol';
import { MainContext, ExtHostContext, IInitData } from './extHost.protocol';
import * as languageConfiguration from 'vs/editor/common/modes/languageConfiguration';
import { TextEditorCursorStyle } from 'vs/editor/common/config/editorOptions';
import { ExtHostThreadService } from 'vs/workbench/services/thread/node/extHostThreadService';
import { ProxyIdentifier } from 'vs/workbench/services/thread/common/threadService';
import { ExtHostDialogs } from 'vs/workbench/api/node/extHostDialogs';
import { MarkdownString } from 'vs/base/common/htmlContent';
export interface IExtensionApiFactory {
(extension: IExtensionDescription): typeof vscode;
@@ -72,37 +74,42 @@ function proposedApiFunction<T>(extension: IExtensionDescription, fn: T): T {
*/
export function createApiFactory(
initData: IInitData,
threadService: IThreadService,
extensionService: ExtHostExtensionService,
telemetryService: ITelemetryService
threadService: ExtHostThreadService,
extensionService: ExtHostExtensionService
): IExtensionApiFactory {
const mainThreadTelemetry = threadService.get(MainContext.MainThreadTelemetry);
// Addressable instances
const col = new InstanceCollection();
const extHostHeapService = col.define(ExtHostContext.ExtHostHeapService).set<ExtHostHeapService>(new ExtHostHeapService());
const extHostDebugService = col.define(ExtHostContext.ExtHostDebugService).set<ExtHostDebugService>(new ExtHostDebugService(threadService));
const extHostDocumentsAndEditors = col.define(ExtHostContext.ExtHostDocumentsAndEditors).set<ExtHostDocumentsAndEditors>(new ExtHostDocumentsAndEditors(threadService));
const extHostDocuments = col.define(ExtHostContext.ExtHostDocuments).set<ExtHostDocuments>(new ExtHostDocuments(threadService, extHostDocumentsAndEditors));
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 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));
const languageFeatures = col.define(ExtHostContext.ExtHostLanguageFeatures).set<ExtHostLanguageFeatures>(new ExtHostLanguageFeatures(threadService, extHostDocuments, extHostCommands, extHostHeapService, extHostDiagnostics));
const extHostFileSystemEvent = col.define(ExtHostContext.ExtHostFileSystemEventService).set<ExtHostFileSystemEventService>(new ExtHostFileSystemEventService());
const extHostQuickOpen = col.define(ExtHostContext.ExtHostQuickOpen).set<ExtHostQuickOpen>(new ExtHostQuickOpen(threadService));
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));
const extHostWindow = col.define(ExtHostContext.ExtHostWindow).set<ExtHostWindow>(new ExtHostWindow(threadService));
col.define(ExtHostContext.ExtHostExtensionService).set(extensionService);
col.finish(false, threadService);
const extHostHeapService = threadService.set(ExtHostContext.ExtHostHeapService, new ExtHostHeapService());
const extHostDocumentsAndEditors = threadService.set(ExtHostContext.ExtHostDocumentsAndEditors, new ExtHostDocumentsAndEditors(threadService, extensionService));
const extHostDocuments = threadService.set(ExtHostContext.ExtHostDocuments, new ExtHostDocuments(threadService, extHostDocumentsAndEditors));
const extHostDocumentContentProviders = threadService.set(ExtHostContext.ExtHostDocumentContentProviders, new ExtHostDocumentContentProvider(threadService, extHostDocumentsAndEditors));
const extHostDocumentSaveParticipant = threadService.set(ExtHostContext.ExtHostDocumentSaveParticipant, new ExtHostDocumentSaveParticipant(extHostDocuments, threadService.get(MainContext.MainThreadWorkspace)));
const extHostEditors = threadService.set(ExtHostContext.ExtHostEditors, new ExtHostEditors(threadService, extHostDocumentsAndEditors));
const extHostCommands = threadService.set(ExtHostContext.ExtHostCommands, new ExtHostCommands(threadService, extHostHeapService));
const extHostTreeViews = threadService.set(ExtHostContext.ExtHostTreeViews, new ExtHostTreeViews(threadService.get(MainContext.MainThreadTreeViews), extHostCommands));
const extHostWorkspace = threadService.set(ExtHostContext.ExtHostWorkspace, new ExtHostWorkspace(threadService, initData.workspace));
const extHostDebugService = threadService.set(ExtHostContext.ExtHostDebugService, new ExtHostDebugService(threadService, extHostWorkspace));
const extHostConfiguration = threadService.set(ExtHostContext.ExtHostConfiguration, new ExtHostConfiguration(threadService.get(MainContext.MainThreadConfiguration), extHostWorkspace, initData.configuration));
const extHostDiagnostics = threadService.set(ExtHostContext.ExtHostDiagnostics, new ExtHostDiagnostics(threadService));
const languageFeatures = threadService.set(ExtHostContext.ExtHostLanguageFeatures, new ExtHostLanguageFeatures(threadService, extHostDocuments, extHostCommands, extHostHeapService, extHostDiagnostics));
const extHostFileSystemEvent = threadService.set(ExtHostContext.ExtHostFileSystemEventService, new ExtHostFileSystemEventService());
const extHostQuickOpen = threadService.set(ExtHostContext.ExtHostQuickOpen, new ExtHostQuickOpen(threadService));
const extHostTerminalService = threadService.set(ExtHostContext.ExtHostTerminalService, new ExtHostTerminalService(threadService));
const extHostSCM = threadService.set(ExtHostContext.ExtHostSCM, new ExtHostSCM(threadService, extHostCommands));
const extHostTask = threadService.set(ExtHostContext.ExtHostTask, new ExtHostTask(threadService));
const extHostCredentials = threadService.set(ExtHostContext.ExtHostCredentials, new ExtHostCredentials(threadService));
const extHostWindow = threadService.set(ExtHostContext.ExtHostWindow, new ExtHostWindow(threadService));
threadService.set(ExtHostContext.ExtHostExtensionService, extensionService);
// Check that no named customers are missing
const expected: ProxyIdentifier<any>[] = Object.keys(ExtHostContext).map((key) => ExtHostContext[key]);
threadService.assertRegistered(expected);
// Other instances
const extHostMessageService = new ExtHostMessageService(threadService);
const extHostDialogs = new ExtHostDialogs(threadService);
const extHostStatusBar = new ExtHostStatusBar(threadService);
const extHostProgress = new ExtHostProgress(threadService.get(MainContext.MainThreadProgress));
const extHostOutputService = new ExtHostOutputService(threadService);
@@ -136,7 +143,7 @@ export function createApiFactory(
return undefined;
}
this._seen.add(apiName);
return telemetryService.publicLog('apiUsage', {
return mainThreadTelemetry.$publicLog('apiUsage', {
name: apiName,
extension: extension.id
});
@@ -238,7 +245,7 @@ export function createApiFactory(
return languageFeatures.registerTypeDefinitionProvider(selector, provider);
},
registerHoverProvider(selector: vscode.DocumentSelector, provider: vscode.HoverProvider): vscode.Disposable {
return languageFeatures.registerHoverProvider(selector, provider);
return languageFeatures.registerHoverProvider(selector, provider, extension.id);
},
registerDocumentHighlightProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentHighlightProvider): vscode.Disposable {
return languageFeatures.registerDocumentHighlightProvider(selector, provider);
@@ -275,7 +282,11 @@ export function createApiFactory(
},
setLanguageConfiguration: (language: string, configuration: vscode.LanguageConfiguration): vscode.Disposable => {
return languageFeatures.setLanguageConfiguration(language, configuration);
}
},
// proposed API
registerColorProvider: proposedApiFunction(extension, (selector: vscode.DocumentSelector, provider: vscode.DocumentColorProvider) => {
return languageFeatures.registerColorProvider(selector, provider);
})
};
// namespace: window
@@ -286,8 +297,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);
@@ -317,13 +336,13 @@ export function createApiFactory(
return extHostWindow.onDidChangeWindowState(listener, thisArg, disposables);
}),
showInformationMessage(message, first, ...rest) {
return extHostMessageService.showMessage(Severity.Info, message, first, rest);
return extHostMessageService.showMessage(extension, Severity.Info, message, first, rest);
},
showWarningMessage(message, first, ...rest) {
return extHostMessageService.showMessage(Severity.Warning, message, first, rest);
return extHostMessageService.showMessage(extension, Severity.Warning, message, first, rest);
},
showErrorMessage(message, first, ...rest) {
return extHostMessageService.showMessage(Severity.Error, message, first, rest);
return extHostMessageService.showMessage(extension, Severity.Error, message, first, rest);
},
showQuickPick(items: any, options: vscode.QuickPickOptions, token?: vscode.CancellationToken) {
return extHostQuickOpen.showQuickPick(items, options, token);
@@ -358,8 +377,11 @@ export function createApiFactory(
},
// proposed API
sampleFunction: proposedApiFunction(extension, () => {
return extHostMessageService.showMessage(Severity.Info, 'Hello Proposed Api!', {}, []);
return extHostMessageService.showMessage(extension, Severity.Info, 'Hello Proposed Api!', {}, []);
}),
showOpenDialog: proposedApiFunction(extension, options => {
return extHostDialogs.showOpenDialog(options);
})
};
// namespace: workspace
@@ -382,8 +404,8 @@ export function createApiFactory(
apiUsage.publicLog('workspace#onDidChangeWorkspaceFolders');
return extHostWorkspace.onDidChangeWorkspace(listener, thisArgs, disposables);
},
asRelativePath: (pathOrUri) => {
return extHostWorkspace.getRelativePath(pathOrUri);
asRelativePath: (pathOrUri, includeWorkspace) => {
return extHostWorkspace.getRelativePath(pathOrUri, includeWorkspace);
},
findFiles: (include, exclude, maxResults?, token?) => {
return extHostWorkspace.findFiles(include, exclude, maxResults, token);
@@ -424,9 +446,6 @@ export function createApiFactory(
});
});
},
registerTextDocumentContentProvider(scheme: string, provider: vscode.TextDocumentContentProvider) {
return extHostDocuments.registerTextDocumentContentProvider(scheme, provider);
},
onDidOpenTextDocument: (listener, thisArgs?, disposables?) => {
return extHostDocuments.onDidAddDocument(listener, thisArgs, disposables);
},
@@ -445,30 +464,33 @@ export function createApiFactory(
onDidChangeConfiguration: (listener: (_: any) => any, thisArgs?: any, disposables?: extHostTypes.Disposable[]) => {
return extHostConfiguration.onDidChangeConfiguration(listener, thisArgs, disposables);
},
getConfiguration: (section?: string): vscode.WorkspaceConfiguration => {
return extHostConfiguration.getConfiguration(section);
getConfiguration: (section?: string, resource?: vscode.Uri): vscode.WorkspaceConfiguration => {
return extHostConfiguration.getConfiguration(section, <URI>resource);
},
registerTextDocumentContentProvider(scheme: string, provider: vscode.TextDocumentContentProvider) {
return extHostDocumentContentProviders.registerTextDocumentContentProvider(scheme, provider);
},
getConfiguration2: proposedApiFunction(extension, (section?: string, resource?: vscode.Uri): vscode.WorkspaceConfiguration => {
return extHostConfiguration.getConfiguration2(section, <URI>resource);
}),
registerTaskProvider: (type: string, provider: vscode.TaskProvider) => {
return extHostTask.registerTaskProvider(extension, provider);
}
},
registerFileSystemProvider: proposedApiFunction(extension, (authority, provider) => {
return extHostWorkspace.registerFileSystemProvider(authority, provider);
})
};
// namespace: scm
const scm: typeof vscode.scm = {
get inputBox() {
return extHostSCM.inputBox;
return extHostSCM.getLastInputBox(extension);
},
createSourceControl(id: string, label: string) {
telemetryService.publicLog('registerSCMProvider', {
mainThreadTelemetry.$publicLog('registerSCMProvider', {
extensionId: extension.id,
providerId: id,
providerLabel: label
});
return extHostSCM.createSourceControl(id, label);
return extHostSCM.createSourceControl(extension, id, label);
}
};
@@ -477,11 +499,8 @@ export function createApiFactory(
get activeDebugSession() {
return extHostDebugService.activeDebugSession;
},
startDebugging: proposedApiFunction(extension, (nameOrConfig: string | vscode.DebugConfiguration) => {
return extHostDebugService.startDebugging(nameOrConfig);
}),
startDebugSession(config: vscode.DebugConfiguration) {
return extHostDebugService.startDebugSession(config);
startDebugging(folder: vscode.WorkspaceFolder | undefined, nameOrConfig: string | vscode.DebugConfiguration) {
return extHostDebugService.startDebugging(folder, nameOrConfig);
},
onDidStartDebugSession(listener, thisArg?, disposables?) {
return extHostDebugService.onDidStartDebugSession(listener, thisArg, disposables);
@@ -494,11 +513,14 @@ export function createApiFactory(
},
onDidReceiveDebugSessionCustomEvent(listener, thisArg?, disposables?) {
return extHostDebugService.onDidReceiveDebugSessionCustomEvent(listener, thisArg, disposables);
}
},
registerDebugConfigurationProvider: proposedApiFunction(extension, (debugType: string, provider: vscode.DebugConfigurationProvider) => {
return extHostDebugService.registerDebugConfigurationProvider(debugType, provider);
}),
};
// namespace: credentials
const credentials: typeof vscode.credentials = {
const credentials = {
readSecret(service: string, account: string): Thenable<string | undefined> {
return extHostCredentials.readSecret(service, account);
},
@@ -511,7 +533,7 @@ export function createApiFactory(
};
return {
const api: typeof vscode = {
version: pkg.version,
// namespaces
commands,
@@ -522,14 +544,12 @@ export function createApiFactory(
workspace,
scm,
debug,
get credentials() {
return proposedApiFunction(extension, () => {
return credentials;
})();
},
// types
CancellationTokenSource: CancellationTokenSource,
CodeLens: extHostTypes.CodeLens,
Color: extHostTypes.Color,
ColorRange: extHostTypes.ColorRange,
EndOfLine: extHostTypes.EndOfLine,
CompletionItem: extHostTypes.CompletionItem,
CompletionItemKind: extHostTypes.CompletionItemKind,
CompletionList: extHostTypes.CompletionList,
@@ -539,11 +559,11 @@ export function createApiFactory(
DocumentHighlight: extHostTypes.DocumentHighlight,
DocumentHighlightKind: extHostTypes.DocumentHighlightKind,
DocumentLink: extHostTypes.DocumentLink,
EndOfLine: extHostTypes.EndOfLine,
EventEmitter: Emitter,
Hover: extHostTypes.Hover,
IndentAction: languageConfiguration.IndentAction,
Location: extHostTypes.Location,
MarkdownString: MarkdownString,
OverviewRulerLane: EditorCommon.OverviewRulerLane,
ParameterInformation: extHostTypes.ParameterInformation,
Position: extHostTypes.Position,
@@ -575,8 +595,13 @@ export function createApiFactory(
TaskGroup: extHostTypes.TaskGroup,
ProcessExecution: extHostTypes.ProcessExecution,
ShellExecution: extHostTypes.ShellExecution,
Task: extHostTypes.Task
Task: extHostTypes.Task,
ConfigurationTarget: extHostTypes.ConfigurationTarget
};
if (extension.enableProposedApi && extension.isBuiltin) {
api['credentials'] = credentials;
}
return api;
};
}
@@ -600,39 +625,16 @@ class Extension<T> implements vscode.Extension<T> {
}
get exports(): T {
return <T>this._extensionService.get(this.id);
return <T>this._extensionService.getExtensionExports(this.id);
}
activate(): Thenable<T> {
return this._extensionService.activateById(this.id).then(() => this.exports);
return this._extensionService.activateById(this.id, false).then(() => this.exports);
}
}
export function initializeExtensionApi(extensionService: ExtHostExtensionService, apiFactory: IExtensionApiFactory): TPromise<void> {
return createExtensionPathIndex(extensionService).then(trie => defineAPI(apiFactory, trie));
}
function createExtensionPathIndex(extensionService: ExtHostExtensionService): TPromise<TrieMap<IExtensionDescription>> {
// create trie to enable fast 'filename -> extension id' look up
const trie = new TrieMap<IExtensionDescription>(TrieMap.PathSplitter);
const extensions = extensionService.getAllExtensionDescriptions().map(ext => {
if (!ext.main) {
return undefined;
}
return new TPromise((resolve, reject) => {
realpath(ext.extensionFolderPath, (err, path) => {
if (err) {
reject(err);
} else {
trie.insert(path, ext);
resolve(void 0);
}
});
});
});
return TPromise.join(extensions).then(() => trie);
return extensionService.getExtensionPathIndex().then(trie => defineAPI(apiFactory, trie));
}
function defineAPI(factory: IExtensionApiFactory, extensionPaths: TrieMap<IExtensionDescription>): void {

View File

@@ -7,7 +7,7 @@
import {
createMainContextProxyIdentifier as createMainId,
createExtHostContextProxyIdentifier as createExtId,
ProxyIdentifier, IThreadService
ProxyIdentifier
} from 'vs/workbench/services/thread/common/threadService';
import * as vscode from 'vscode';
@@ -46,8 +46,11 @@ import { ISelection, Selection } from 'vs/editor/common/core/selection';
import { ITreeItem } from 'vs/workbench/parts/views/common/views';
import { ThemeColor } from 'vs/platform/theme/common/themeService';
import { IDisposable } from 'vs/base/common/lifecycle';
import { SerializedError } from 'vs/base/common/errors';
export interface IEnvironment {
isExtensionDevelopmentDebug: boolean;
enableProposedApiForAll: boolean;
enableProposedApiFor: string | string[];
appSettingsHome: string;
@@ -72,75 +75,67 @@ export interface IInitData {
telemetryInfo: ITelemetryInfo;
}
export interface InstanceSetter<T> {
set<R extends T>(instance: T): R;
export interface IExtHostContext {
/**
* Returns a proxy to an object addressable/named in the extension host process.
*/
get<T>(identifier: ProxyIdentifier<T>): T;
/**
* Register manually created instance.
*/
set<T, R extends T>(identifier: ProxyIdentifier<T>, instance: R): R;
}
export class InstanceCollection {
private _items: { [id: string]: any; };
constructor() {
this._items = Object.create(null);
}
public define<T>(id: ProxyIdentifier<T>): InstanceSetter<T> {
let that = this;
return new class {
set<R extends T>(value: T): R {
that._set(id, value);
return <R>value;
}
};
}
_set<T>(id: ProxyIdentifier<T>, value: T): void {
this._items[id.id] = value;
}
public finish(isMain: boolean, threadService: IThreadService): void {
let expected = (isMain ? MainContext : ExtHostContext);
Object.keys(expected).forEach((key) => {
let id = expected[key];
let value = this._items[id.id];
if (!value) {
throw new Error(`Missing actor ${key} (isMain: ${id.isMain}, id: ${id.id})`);
}
threadService.set<any>(id, value);
});
}
export interface IMainContext {
/**
* Returns a proxy to an object addressable/named in the main/renderer process.
*/
get<T>(identifier: ProxyIdentifier<T>): T;
}
function ni() { return new Error('Not implemented'); }
// --- main thread
export abstract class MainThreadCommandsShape {
$registerCommand(id: string): TPromise<any> { throw ni(); }
$unregisterCommand(id: string): TPromise<any> { throw ni(); }
$executeCommand<T>(id: string, args: any[]): Thenable<T> { throw ni(); }
$getCommands(): Thenable<string[]> { throw ni(); }
export interface MainThreadCommandsShape extends IDisposable {
$registerCommand(id: string): TPromise<any>;
$unregisterCommand(id: string): TPromise<any>;
$executeCommand<T>(id: string, args: any[]): Thenable<T>;
$getCommands(): Thenable<string[]>;
}
export abstract class MainThreadConfigurationShape {
$updateConfigurationOption(target: ConfigurationTarget, key: string, value: any): TPromise<void> { throw ni(); }
$removeConfigurationOption(target: ConfigurationTarget, key: string): TPromise<void> { throw ni(); }
export interface MainThreadConfigurationShape extends IDisposable {
$updateConfigurationOption(target: ConfigurationTarget, key: string, value: any, resource: URI): TPromise<void>;
$removeConfigurationOption(target: ConfigurationTarget, key: string, resource: URI): TPromise<void>;
}
export abstract class MainThreadDiagnosticsShape {
$changeMany(owner: string, entries: [URI, IMarkerData[]][]): TPromise<any> { throw ni(); }
$clear(owner: string): TPromise<any> { throw ni(); }
export interface MainThreadDiagnosticsShape extends IDisposable {
$changeMany(owner: string, entries: [URI, IMarkerData[]][]): TPromise<any>;
$clear(owner: string): TPromise<any>;
}
export abstract class MainThreadDocumentsShape {
$tryCreateDocument(options?: { language?: string; content?: string; }): TPromise<any> { throw ni(); }
$tryOpenDocument(uri: URI): TPromise<any> { throw ni(); }
$registerTextContentProvider(handle: number, scheme: string): void { throw ni(); }
$onVirtualDocumentChange(uri: URI, value: ITextSource): void { throw ni(); }
$unregisterTextContentProvider(handle: number): void { throw ni(); }
$trySaveDocument(uri: URI): TPromise<boolean> { throw ni(); }
export interface MainThreadDialogOptions {
uri?: URI;
openLabel?: string;
openFiles?: boolean;
openFolders?: boolean;
openMany?: boolean;
}
export interface MainThreadDiaglogsShape extends IDisposable {
$showOpenDialog(options: MainThreadDialogOptions): TPromise<string[]>;
}
export interface MainThreadDocumentContentProvidersShape extends IDisposable {
$registerTextContentProvider(handle: number, scheme: string): void;
$unregisterTextContentProvider(handle: number): void;
$onVirtualDocumentChange(uri: URI, value: ITextSource): void;
}
export interface MainThreadDocumentsShape extends IDisposable {
$tryCreateDocument(options?: { language?: string; content?: string; }): TPromise<any>;
$tryOpenDocument(uri: URI): TPromise<any>;
$trySaveDocument(uri: URI): TPromise<boolean>;
}
export interface ISelectionChangeEvent {
selections: Selection[];
@@ -186,125 +181,133 @@ export interface ITextDocumentShowOptions {
selection?: IRange;
}
export abstract class MainThreadEditorsShape {
$tryShowTextDocument(resource: URI, options: ITextDocumentShowOptions): TPromise<string> { throw ni(); }
$registerTextEditorDecorationType(key: string, options: editorCommon.IDecorationRenderOptions): void { throw ni(); }
$removeTextEditorDecorationType(key: string): void { throw ni(); }
$tryShowEditor(id: string, position: EditorPosition): TPromise<void> { throw ni(); }
$tryHideEditor(id: string): TPromise<void> { throw ni(); }
$trySetOptions(id: string, options: ITextEditorConfigurationUpdate): TPromise<any> { throw ni(); }
$trySetDecorations(id: string, key: string, ranges: editorCommon.IDecorationOptions[]): TPromise<any> { throw ni(); }
$tryRevealRange(id: string, range: IRange, revealType: TextEditorRevealType): TPromise<any> { throw ni(); }
$trySetSelections(id: string, selections: ISelection[]): TPromise<any> { throw ni(); }
$tryApplyEdits(id: string, modelVersionId: number, edits: editorCommon.ISingleEditOperation[], opts: IApplyEditsOptions): TPromise<boolean> { throw ni(); }
$tryInsertSnippet(id: string, template: string, selections: IRange[], opts: IUndoStopOptions): TPromise<any> { throw ni(); }
$getDiffInformation(id: string): TPromise<editorCommon.ILineChange[]> { throw ni(); }
export interface MainThreadEditorsShape extends IDisposable {
$tryShowTextDocument(resource: URI, options: ITextDocumentShowOptions): TPromise<string>;
$registerTextEditorDecorationType(key: string, options: editorCommon.IDecorationRenderOptions): void;
$removeTextEditorDecorationType(key: string): void;
$tryShowEditor(id: string, position: EditorPosition): TPromise<void>;
$tryHideEditor(id: string): TPromise<void>;
$trySetOptions(id: string, options: ITextEditorConfigurationUpdate): TPromise<any>;
$trySetDecorations(id: string, key: string, ranges: editorCommon.IDecorationOptions[]): TPromise<any>;
$tryRevealRange(id: string, range: IRange, revealType: TextEditorRevealType): TPromise<any>;
$trySetSelections(id: string, selections: ISelection[]): TPromise<any>;
$tryApplyEdits(id: string, modelVersionId: number, edits: editorCommon.ISingleEditOperation[], opts: IApplyEditsOptions): TPromise<boolean>;
$tryInsertSnippet(id: string, template: string, selections: IRange[], opts: IUndoStopOptions): TPromise<any>;
$getDiffInformation(id: string): TPromise<editorCommon.ILineChange[]>;
}
export abstract class MainThreadTreeViewsShape {
$registerView(treeViewId: string): void { throw ni(); }
$refresh(treeViewId: string, treeItemHandle?: number): void { throw ni(); }
export interface MainThreadTreeViewsShape extends IDisposable {
$registerView(treeViewId: string): void;
$refresh(treeViewId: string, treeItemHandles: number[]): void;
}
export abstract class MainThreadErrorsShape {
onUnexpectedExtHostError(err: any): void { throw ni(); }
export interface MainThreadErrorsShape extends IDisposable {
$onUnexpectedError(err: any | SerializedError, extensionId: string | undefined): void;
}
export abstract class MainThreadLanguageFeaturesShape {
$unregister(handle: number): TPromise<any> { throw ni(); }
$registerOutlineSupport(handle: number, selector: vscode.DocumentSelector): TPromise<any> { throw ni(); }
$registerCodeLensSupport(handle: number, selector: vscode.DocumentSelector, eventHandle: number): TPromise<any> { throw ni(); }
$emitCodeLensEvent(eventHandle: number, event?: any): TPromise<any> { throw ni(); }
$registerDeclaractionSupport(handle: number, selector: vscode.DocumentSelector): TPromise<any> { throw ni(); }
$registerImplementationSupport(handle: number, selector: vscode.DocumentSelector): TPromise<any> { throw ni(); }
$registerTypeDefinitionSupport(handle: number, selector: vscode.DocumentSelector): TPromise<any> { throw ni(); }
$registerHoverProvider(handle: number, selector: vscode.DocumentSelector): TPromise<any> { throw ni(); }
$registerDocumentHighlightProvider(handle: number, selector: vscode.DocumentSelector): TPromise<any> { throw ni(); }
$registerReferenceSupport(handle: number, selector: vscode.DocumentSelector): TPromise<any> { throw ni(); }
$registerQuickFixSupport(handle: number, selector: vscode.DocumentSelector): TPromise<any> { throw ni(); }
$registerDocumentFormattingSupport(handle: number, selector: vscode.DocumentSelector): TPromise<any> { throw ni(); }
$registerRangeFormattingSupport(handle: number, selector: vscode.DocumentSelector): TPromise<any> { throw ni(); }
$registerOnTypeFormattingSupport(handle: number, selector: vscode.DocumentSelector, autoFormatTriggerCharacters: string[]): TPromise<any> { throw ni(); }
$registerNavigateTypeSupport(handle: number): TPromise<any> { throw ni(); }
$registerRenameSupport(handle: number, selector: vscode.DocumentSelector): TPromise<any> { throw ni(); }
$registerSuggestSupport(handle: number, selector: vscode.DocumentSelector, triggerCharacters: string[]): TPromise<any> { throw ni(); }
$registerSignatureHelpProvider(handle: number, selector: vscode.DocumentSelector, triggerCharacter: string[]): TPromise<any> { throw ni(); }
$registerDocumentLinkProvider(handle: number, selector: vscode.DocumentSelector): TPromise<any> { throw ni(); }
$setLanguageConfiguration(handle: number, languageId: string, configuration: vscode.LanguageConfiguration): TPromise<any> { throw ni(); }
export interface MainThreadLanguageFeaturesShape extends IDisposable {
$unregister(handle: number): TPromise<any>;
$registerOutlineSupport(handle: number, selector: vscode.DocumentSelector): TPromise<any>;
$registerCodeLensSupport(handle: number, selector: vscode.DocumentSelector, eventHandle: number): TPromise<any>;
$emitCodeLensEvent(eventHandle: number, event?: any): TPromise<any>;
$registerDeclaractionSupport(handle: number, selector: vscode.DocumentSelector): TPromise<any>;
$registerImplementationSupport(handle: number, selector: vscode.DocumentSelector): TPromise<any>;
$registerTypeDefinitionSupport(handle: number, selector: vscode.DocumentSelector): TPromise<any>;
$registerHoverProvider(handle: number, selector: vscode.DocumentSelector): TPromise<any>;
$registerDocumentHighlightProvider(handle: number, selector: vscode.DocumentSelector): TPromise<any>;
$registerReferenceSupport(handle: number, selector: vscode.DocumentSelector): TPromise<any>;
$registerQuickFixSupport(handle: number, selector: vscode.DocumentSelector): TPromise<any>;
$registerDocumentFormattingSupport(handle: number, selector: vscode.DocumentSelector): TPromise<any>;
$registerRangeFormattingSupport(handle: number, selector: vscode.DocumentSelector): TPromise<any>;
$registerOnTypeFormattingSupport(handle: number, selector: vscode.DocumentSelector, autoFormatTriggerCharacters: string[]): TPromise<any>;
$registerNavigateTypeSupport(handle: number): TPromise<any>;
$registerRenameSupport(handle: number, selector: vscode.DocumentSelector): TPromise<any>;
$registerSuggestSupport(handle: number, selector: vscode.DocumentSelector, triggerCharacters: string[]): TPromise<any>;
$registerSignatureHelpProvider(handle: number, selector: vscode.DocumentSelector, triggerCharacter: string[]): TPromise<any>;
$registerDocumentLinkProvider(handle: number, selector: vscode.DocumentSelector): TPromise<any>;
$registerColorFormats(formats: IRawColorFormatMap): TPromise<any>;
$registerDocumentColorProvider(handle: number, selector: vscode.DocumentSelector): TPromise<any>;
$setLanguageConfiguration(handle: number, languageId: string, configuration: vscode.LanguageConfiguration): TPromise<any>;
}
export abstract class MainThreadLanguagesShape {
$getLanguages(): TPromise<string[]> { throw ni(); }
export interface MainThreadLanguagesShape extends IDisposable {
$getLanguages(): TPromise<string[]>;
}
export abstract class MainThreadMessageServiceShape {
$showMessage(severity: Severity, message: string, options: vscode.MessageOptions, commands: { title: string; isCloseAffordance: boolean; handle: number; }[]): Thenable<number> { throw ni(); }
export interface MainThreadMessageOptions {
extension?: IExtensionDescription;
modal?: boolean;
}
export abstract class MainThreadOutputServiceShape {
$append(channelId: string, label: string, value: string): TPromise<void> { throw ni(); }
$clear(channelId: string, label: string): TPromise<void> { throw ni(); }
$dispose(channelId: string, label: string): TPromise<void> { throw ni(); }
$reveal(channelId: string, label: string, preserveFocus: boolean): TPromise<void> { throw ni(); }
$close(channelId: string): TPromise<void> { throw ni(); }
export interface MainThreadMessageServiceShape extends IDisposable {
$showMessage(severity: Severity, message: string, options: MainThreadMessageOptions, commands: { title: string; isCloseAffordance: boolean; handle: number; }[]): Thenable<number>;
}
export abstract class MainThreadProgressShape {
$startProgress(handle: number, options: IProgressOptions): void { throw ni(); };
$progressReport(handle: number, message: IProgressStep): void { throw ni(); }
$progressEnd(handle: number): void { throw ni(); }
export interface MainThreadOutputServiceShape extends IDisposable {
$append(channelId: string, label: string, value: string): TPromise<void>;
$clear(channelId: string, label: string): TPromise<void>;
$dispose(channelId: string, label: string): TPromise<void>;
$reveal(channelId: string, label: string, preserveFocus: boolean): TPromise<void>;
$close(channelId: string): TPromise<void>;
}
export abstract class MainThreadTerminalServiceShape {
$createTerminal(name?: string, shellPath?: string, shellArgs?: string[], waitOnExit?: boolean): TPromise<number> { throw ni(); }
$dispose(terminalId: number): void { throw ni(); }
$hide(terminalId: number): void { throw ni(); }
$sendText(terminalId: number, text: string, addNewLine: boolean): void { throw ni(); }
$show(terminalId: number, preserveFocus: boolean): void { throw ni(); }
export interface MainThreadProgressShape extends IDisposable {
$startProgress(handle: number, options: IProgressOptions): void;
$progressReport(handle: number, message: IProgressStep): void;
$progressEnd(handle: number): void;
}
export interface MainThreadTerminalServiceShape extends IDisposable {
$createTerminal(name?: string, shellPath?: string, shellArgs?: string[], waitOnExit?: boolean): TPromise<number>;
$dispose(terminalId: number): void;
$hide(terminalId: number): void;
$sendText(terminalId: number, text: string, addNewLine: boolean): void;
$show(terminalId: number, preserveFocus: boolean): void;
}
export interface MyQuickPickItems extends IPickOpenEntry {
handle: number;
}
export abstract class MainThreadQuickOpenShape {
$show(options: IPickOptions): TPromise<number> { throw ni(); }
$setItems(items: MyQuickPickItems[]): TPromise<any> { throw ni(); }
$setError(error: Error): TPromise<any> { throw ni(); }
$input(options: vscode.InputBoxOptions, validateInput: boolean): TPromise<string> { throw ni(); }
export interface MainThreadQuickOpenShape extends IDisposable {
$show(options: IPickOptions): TPromise<number>;
$setItems(items: MyQuickPickItems[]): TPromise<any>;
$setError(error: Error): TPromise<any>;
$input(options: vscode.InputBoxOptions, validateInput: boolean): TPromise<string>;
}
export abstract class MainThreadStatusBarShape {
$setEntry(id: number, extensionId: string, text: string, tooltip: string, command: string, color: string | ThemeColor, alignment: MainThreadStatusBarAlignment, priority: number): void { throw ni(); }
$dispose(id: number) { throw ni(); }
export interface MainThreadStatusBarShape extends IDisposable {
$setEntry(id: number, extensionId: string, text: string, tooltip: string, command: string, color: string | ThemeColor, alignment: MainThreadStatusBarAlignment, priority: number): void;
$dispose(id: number);
}
export abstract class MainThreadStorageShape {
$getValue<T>(shared: boolean, key: string): TPromise<T> { throw ni(); }
$setValue(shared: boolean, key: string, value: any): TPromise<any> { throw ni(); }
export interface MainThreadStorageShape extends IDisposable {
$getValue<T>(shared: boolean, key: string): TPromise<T>;
$setValue(shared: boolean, key: string, value: any): TPromise<any>;
}
export abstract class MainThreadTelemetryShape {
$publicLog(eventName: string, data?: any): void { throw ni(); }
$getTelemetryInfo(): TPromise<ITelemetryInfo> { throw ni(); }
export interface MainThreadTelemetryShape extends IDisposable {
$publicLog(eventName: string, data?: any): void;
}
export abstract class MainThreadWorkspaceShape {
$startSearch(include: string, exclude: string, maxResults: number, requestId: number): Thenable<URI[]> { throw ni(); }
$cancelSearch(requestId: number): Thenable<boolean> { throw ni(); }
$saveAll(includeUntitled?: boolean): Thenable<boolean> { throw ni(); }
$applyWorkspaceEdit(edits: IResourceEdit[]): TPromise<boolean> { throw ni(); }
export interface MainThreadWorkspaceShape extends IDisposable {
$startSearch(include: string, exclude: string, maxResults: number, requestId: number): Thenable<URI[]>;
$cancelSearch(requestId: number): Thenable<boolean>;
$saveAll(includeUntitled?: boolean): Thenable<boolean>;
$applyWorkspaceEdit(edits: IResourceEdit[]): TPromise<boolean>;
$registerFileSystemProvider(handle: number, authority: string): void;
$onFileSystemChange(handle: number, resource: URI): void;
}
export abstract class MainThreadTaskShape {
$registerTaskProvider(handle: number): TPromise<any> { throw ni(); }
$unregisterTaskProvider(handle: number): TPromise<any> { throw ni(); }
export interface MainThreadTaskShape extends IDisposable {
$registerTaskProvider(handle: number): TPromise<any>;
$unregisterTaskProvider(handle: number): TPromise<any>;
}
export abstract class MainProcessExtensionServiceShape {
$localShowMessage(severity: Severity, msg: string): void { throw ni(); }
$onExtensionActivated(extensionId: string): void { throw ni(); }
$onExtensionActivationFailed(extensionId: string): void { throw ni(); }
export interface MainThreadExtensionServiceShape extends IDisposable {
$localShowMessage(severity: Severity, msg: string): void;
$onExtensionActivated(extensionId: string, startup: boolean, codeLoadingTime: number, activateCallTime: number, activateResolvedTime: number): void;
$onExtensionActivationFailed(extensionId: string): void;
}
export interface SCMProviderFeatures {
@@ -324,57 +327,64 @@ export type SCMRawResource = [
string /*resourceUri*/,
modes.Command /*command*/,
string[] /*icons: light, dark*/,
string /*tooltip*/,
boolean /*strike through*/,
boolean /*faded*/
];
export abstract class MainThreadSCMShape {
$registerSourceControl(handle: number, id: string, label: string): void { throw ni(); }
$updateSourceControl(handle: number, features: SCMProviderFeatures): void { throw ni(); }
$unregisterSourceControl(handle: number): void { throw ni(); }
export interface MainThreadSCMShape extends IDisposable {
$registerSourceControl(handle: number, id: string, label: string): void;
$updateSourceControl(handle: number, features: SCMProviderFeatures): void;
$unregisterSourceControl(handle: number): void;
$registerGroup(sourceControlHandle: number, handle: number, id: string, label: string): void { throw ni(); }
$updateGroup(sourceControlHandle: number, handle: number, features: SCMGroupFeatures): void { throw ni(); }
$updateGroupLabel(sourceControlHandle: number, handle: number, label: string): void { throw ni(); }
$updateGroupResourceStates(sourceControlHandle: number, groupHandle: number, resources: SCMRawResource[]): void { throw ni(); }
$unregisterGroup(sourceControlHandle: number, handle: number): void { throw ni(); }
$registerGroup(sourceControlHandle: number, handle: number, id: string, label: string): void;
$updateGroup(sourceControlHandle: number, handle: number, features: SCMGroupFeatures): void;
$updateGroupLabel(sourceControlHandle: number, handle: number, label: string): void;
$updateGroupResourceStates(sourceControlHandle: number, groupHandle: number, resources: SCMRawResource[]): void;
$unregisterGroup(sourceControlHandle: number, handle: number): void;
$setInputBoxValue(value: string): void { throw ni(); }
$setInputBoxValue(sourceControlHandle: number, value: string): void;
}
export type DebugSessionUUID = string;
export abstract class MainThreadDebugServiceShape {
$startDebugging(nameOrConfig: string | vscode.DebugConfiguration): TPromise<boolean> { throw ni(); }
$startDebugSession(config: vscode.DebugConfiguration): TPromise<DebugSessionUUID> { throw ni(); }
$customDebugAdapterRequest(id: DebugSessionUUID, command: string, args: any): TPromise<any> { throw ni(); }
export interface MainThreadDebugServiceShape extends IDisposable {
$registerDebugConfigurationProvider(type: string, hasProvideMethod: boolean, hasResolveMethod: boolean, handle: number): TPromise<any>;
$unregisterDebugConfigurationProvider(handle: number): TPromise<any>;
$startDebugging(folderUri: URI | undefined, nameOrConfig: string | vscode.DebugConfiguration): TPromise<boolean>;
$startDebugSession(folderUri: URI | undefined, config: vscode.DebugConfiguration): TPromise<DebugSessionUUID>;
$customDebugAdapterRequest(id: DebugSessionUUID, command: string, args: any): TPromise<any>;
}
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(); }
export interface MainThreadCredentialsShape extends IDisposable {
$readSecret(service: string, account: string): Thenable<string | undefined>;
$writeSecret(service: string, account: string, secret: string): Thenable<void>;
$deleteSecret(service: string, account: string): Thenable<boolean>;
}
export abstract class MainThreadWindowShape {
$getWindowVisibility(): TPromise<boolean> { throw ni(); }
export interface MainThreadWindowShape extends IDisposable {
$getWindowVisibility(): TPromise<boolean>;
}
// -- extension host
export abstract class ExtHostCommandsShape {
$executeContributedCommand<T>(id: string, ...args: any[]): Thenable<T> { throw ni(); }
$getContributedCommandHandlerDescriptions(): TPromise<{ [id: string]: string | ICommandHandlerDescription }> { throw ni(); }
export interface ExtHostCommandsShape {
$executeContributedCommand<T>(id: string, ...args: any[]): Thenable<T>;
$getContributedCommandHandlerDescriptions(): TPromise<{ [id: string]: string | ICommandHandlerDescription }>;
}
export abstract class ExtHostConfigurationShape {
$acceptConfigurationChanged(data: IConfigurationData<any>) { throw ni(); }
export interface ExtHostConfigurationShape {
$acceptConfigurationChanged(data: IConfigurationData<any>);
}
export abstract class ExtHostDiagnosticsShape {
export interface ExtHostDiagnosticsShape {
}
export interface ExtHostDocumentContentProvidersShape {
$provideTextDocumentContent(handle: number, uri: URI): TPromise<string>;
}
export interface IModelAddedData {
url: URI;
versionId: number;
@@ -383,16 +393,15 @@ export interface IModelAddedData {
modeId: string;
isDirty: boolean;
}
export abstract class ExtHostDocumentsShape {
$provideTextDocumentContent(handle: number, uri: URI): TPromise<string> { throw ni(); }
$acceptModelModeChanged(strURL: string, oldModeId: string, newModeId: string): void { throw ni(); }
$acceptModelSaved(strURL: string): void { throw ni(); }
$acceptDirtyStateChanged(strURL: string, isDirty: boolean): void { throw ni(); }
$acceptModelChanged(strURL: string, e: IModelChangedEvent, isDirty: boolean): void { throw ni(); }
export interface ExtHostDocumentsShape {
$acceptModelModeChanged(strURL: string, oldModeId: string, newModeId: string): void;
$acceptModelSaved(strURL: string): void;
$acceptDirtyStateChanged(strURL: string, isDirty: boolean): void;
$acceptModelChanged(strURL: string, e: IModelChangedEvent, isDirty: boolean): void;
}
export abstract class ExtHostDocumentSaveParticipantShape {
$participateInSave(resource: URI, reason: SaveReason): TPromise<boolean[]> { throw ni(); }
export interface ExtHostDocumentSaveParticipantShape {
$participateInSave(resource: URI, reason: SaveReason): TPromise<boolean[]>;
}
export interface ITextEditorAddData {
@@ -405,10 +414,10 @@ export interface ITextEditorAddData {
export interface ITextEditorPositionData {
[id: string]: EditorPosition;
}
export abstract class ExtHostEditorsShape {
$acceptOptionsChanged(id: string, opts: IResolvedTextEditorConfiguration): void { throw ni(); }
$acceptSelectionsChanged(id: string, event: ISelectionChangeEvent): void { throw ni(); }
$acceptEditorPositionData(data: ITextEditorPositionData): void { throw ni(); }
export interface ExtHostEditorsShape {
$acceptOptionsChanged(id: string, opts: IResolvedTextEditorConfiguration): void;
$acceptSelectionsChanged(id: string, event: ISelectionChangeEvent): void;
$acceptEditorPositionData(data: ITextEditorPositionData): void;
}
export interface IDocumentsAndEditorsDelta {
@@ -419,21 +428,23 @@ export interface IDocumentsAndEditorsDelta {
newActiveEditor?: string;
}
export abstract class ExtHostDocumentsAndEditorsShape {
$acceptDocumentsAndEditorsDelta(delta: IDocumentsAndEditorsDelta): void { throw ni(); }
export interface ExtHostDocumentsAndEditorsShape {
$acceptDocumentsAndEditorsDelta(delta: IDocumentsAndEditorsDelta): void;
}
export abstract class ExtHostTreeViewsShape {
$getElements(treeViewId: string): TPromise<ITreeItem[]> { throw ni(); }
$getChildren(treeViewId: string, treeItemHandle: number): TPromise<ITreeItem[]> { throw ni(); }
export interface ExtHostTreeViewsShape {
$getElements(treeViewId: string): TPromise<ITreeItem[]>;
$getChildren(treeViewId: string, treeItemHandle: number): TPromise<ITreeItem[]>;
}
export abstract class ExtHostWorkspaceShape {
$acceptWorkspaceData(workspace: IWorkspaceData): void { throw ni(); }
export interface ExtHostWorkspaceShape {
$acceptWorkspaceData(workspace: IWorkspaceData): void;
$resolveFile(handle: number, resource: URI): TPromise<string>;
$storeFile(handle: number, resource: URI, content: string): TPromise<any>;
}
export abstract class ExtHostExtensionServiceShape {
$activateExtension(extensionDescription: IExtensionDescription): TPromise<void> { throw ni(); }
export interface ExtHostExtensionServiceShape {
$activateByEvent(activationEvent: string): TPromise<void>;
}
export interface FileSystemEvents {
@@ -441,8 +452,8 @@ export interface FileSystemEvents {
changed: URI[];
deleted: URI[];
}
export abstract class ExtHostFileSystemEventServiceShape {
$onFileEvent(events: FileSystemEvents) { throw ni(); }
export interface ExtHostFileSystemEventServiceShape {
$onFileEvent(events: FileSystemEvents);
}
export interface ObjectIdentifier {
@@ -460,117 +471,128 @@ export namespace ObjectIdentifier {
}
}
export abstract class ExtHostHeapServiceShape {
$onGarbageCollection(ids: number[]): void { throw ni(); }
export interface ExtHostHeapServiceShape {
$onGarbageCollection(ids: number[]): void;
}
export interface IRawColorInfo {
color: [number, number, number, number];
availableFormats: (number | [number, number])[];
range: IRange;
}
export abstract class ExtHostLanguageFeaturesShape {
$provideDocumentSymbols(handle: number, resource: URI): TPromise<modes.SymbolInformation[]> { throw ni(); }
$provideCodeLenses(handle: number, resource: URI): TPromise<modes.ICodeLensSymbol[]> { throw ni(); }
$resolveCodeLens(handle: number, resource: URI, symbol: modes.ICodeLensSymbol): TPromise<modes.ICodeLensSymbol> { throw ni(); }
$provideDefinition(handle: number, resource: URI, position: IPosition): TPromise<modes.Definition> { throw ni(); }
$provideImplementation(handle: number, resource: URI, position: IPosition): TPromise<modes.Definition> { throw ni(); }
$provideTypeDefinition(handle: number, resource: URI, position: IPosition): TPromise<modes.Definition> { throw ni(); }
$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.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(); }
$provideWorkspaceSymbols(handle: number, search: string): TPromise<modes.SymbolInformation[]> { throw ni(); }
$resolveWorkspaceSymbol(handle: number, symbol: modes.SymbolInformation): TPromise<modes.SymbolInformation> { throw ni(); }
$provideRenameEdits(handle: number, resource: URI, position: IPosition, newName: string): TPromise<modes.WorkspaceEdit> { throw ni(); }
$provideCompletionItems(handle: number, resource: URI, position: IPosition): TPromise<modes.ISuggestResult> { throw ni(); }
$resolveCompletionItem(handle: number, resource: URI, position: IPosition, suggestion: modes.ISuggestion): TPromise<modes.ISuggestion> { throw ni(); }
$provideSignatureHelp(handle: number, resource: URI, position: IPosition): TPromise<modes.SignatureHelp> { throw ni(); }
$provideDocumentLinks(handle: number, resource: URI): TPromise<modes.ILink[]> { throw ni(); }
$resolveDocumentLink(handle: number, link: modes.ILink): TPromise<modes.ILink> { throw ni(); }
export type IRawColorFormatMap = [number, string][];
export interface ExtHostLanguageFeaturesShape {
$provideDocumentSymbols(handle: number, resource: URI): TPromise<modes.SymbolInformation[]>;
$provideCodeLenses(handle: number, resource: URI): TPromise<modes.ICodeLensSymbol[]>;
$resolveCodeLens(handle: number, resource: URI, symbol: modes.ICodeLensSymbol): TPromise<modes.ICodeLensSymbol>;
$provideDefinition(handle: number, resource: URI, position: IPosition): TPromise<modes.Definition>;
$provideImplementation(handle: number, resource: URI, position: IPosition): TPromise<modes.Definition>;
$provideTypeDefinition(handle: number, resource: URI, position: IPosition): TPromise<modes.Definition>;
$provideHover(handle: number, resource: URI, position: IPosition): TPromise<modes.Hover>;
$provideDocumentHighlights(handle: number, resource: URI, position: IPosition): TPromise<modes.DocumentHighlight[]>;
$provideReferences(handle: number, resource: URI, position: IPosition, context: modes.ReferenceContext): TPromise<modes.Location[]>;
$provideCodeActions(handle: number, resource: URI, range: IRange): TPromise<modes.Command[]>;
$provideDocumentFormattingEdits(handle: number, resource: URI, options: modes.FormattingOptions): TPromise<editorCommon.ISingleEditOperation[]>;
$provideDocumentRangeFormattingEdits(handle: number, resource: URI, range: IRange, options: modes.FormattingOptions): TPromise<editorCommon.ISingleEditOperation[]>;
$provideOnTypeFormattingEdits(handle: number, resource: URI, position: IPosition, ch: string, options: modes.FormattingOptions): TPromise<editorCommon.ISingleEditOperation[]>;
$provideWorkspaceSymbols(handle: number, search: string): TPromise<modes.SymbolInformation[]>;
$resolveWorkspaceSymbol(handle: number, symbol: modes.SymbolInformation): TPromise<modes.SymbolInformation>;
$provideRenameEdits(handle: number, resource: URI, position: IPosition, newName: string): TPromise<modes.WorkspaceEdit>;
$provideCompletionItems(handle: number, resource: URI, position: IPosition): TPromise<modes.ISuggestResult>;
$resolveCompletionItem(handle: number, resource: URI, position: IPosition, suggestion: modes.ISuggestion): TPromise<modes.ISuggestion>;
$provideSignatureHelp(handle: number, resource: URI, position: IPosition): TPromise<modes.SignatureHelp>;
$provideDocumentLinks(handle: number, resource: URI): TPromise<modes.ILink[]>;
$provideDocumentColors(handle: number, resource: URI): TPromise<IRawColorInfo[]>;
$resolveDocumentLink(handle: number, link: modes.ILink): TPromise<modes.ILink>;
}
export abstract class ExtHostQuickOpenShape {
$onItemSelected(handle: number): void { throw ni(); }
$validateInput(input: string): TPromise<string> { throw ni(); }
export interface ExtHostQuickOpenShape {
$onItemSelected(handle: number): void;
$validateInput(input: string): TPromise<string>;
}
export abstract class ExtHostTerminalServiceShape {
$acceptTerminalClosed(id: number): void { throw ni(); }
$acceptTerminalProcessId(id: number, processId: number): void { throw ni(); }
export interface ExtHostTerminalServiceShape {
$acceptTerminalClosed(id: number): void;
$acceptTerminalProcessId(id: number, processId: number): void;
}
export abstract class ExtHostSCMShape {
$provideOriginalResource(sourceControlHandle: number, uri: URI): TPromise<URI> { throw ni(); }
$onActiveSourceControlChange(sourceControlHandle: number): TPromise<void> { throw ni(); }
$onInputBoxValueChange(value: string): TPromise<void> { throw ni(); }
$onInputBoxAcceptChanges(): TPromise<void> { throw ni(); }
export interface ExtHostSCMShape {
$provideOriginalResource(sourceControlHandle: number, uri: URI): TPromise<URI>;
$onInputBoxValueChange(sourceControlHandle: number, value: string): TPromise<void>;
}
export abstract class ExtHostTaskShape {
$provideTasks(handle: number): TPromise<TaskSet> { throw ni(); }
export interface ExtHostTaskShape {
$provideTasks(handle: number): TPromise<TaskSet>;
}
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 interface ExtHostDebugServiceShape {
$resolveDebugConfiguration(handle: number, folder: URI | undefined, debugConfiguration: any): TPromise<any>;
$provideDebugConfigurations(handle: number, folder: URI | undefined): TPromise<any[]>;
$acceptDebugSessionStarted(id: DebugSessionUUID, type: string, name: string): void;
$acceptDebugSessionTerminated(id: DebugSessionUUID, type: string, name: string): void;
$acceptDebugSessionActiveChanged(id: DebugSessionUUID | undefined, type?: string, name?: string): void;
$acceptDebugSessionCustomEvent(id: DebugSessionUUID, type: string, name: string, event: any): void;
}
export abstract class ExtHostCredentialsShape {
export interface ExtHostCredentialsShape {
}
export abstract class ExtHostWindowShape {
$onDidChangeWindowFocus(value: boolean): void { throw ni(); }
export interface ExtHostWindowShape {
$onDidChangeWindowFocus(value: boolean): void;
}
// --- proxy identifiers
export const MainContext = {
MainThreadCommands: createMainId<MainThreadCommandsShape>('MainThreadCommands', MainThreadCommandsShape),
MainThreadConfiguration: createMainId<MainThreadConfigurationShape>('MainThreadConfiguration', MainThreadConfigurationShape),
MainThreadDebugService: createMainId<MainThreadDebugServiceShape>('MainThreadDebugService', MainThreadDebugServiceShape),
MainThreadDiagnostics: createMainId<MainThreadDiagnosticsShape>('MainThreadDiagnostics', MainThreadDiagnosticsShape),
MainThreadDocuments: createMainId<MainThreadDocumentsShape>('MainThreadDocuments', MainThreadDocumentsShape),
MainThreadEditors: createMainId<MainThreadEditorsShape>('MainThreadEditors', MainThreadEditorsShape),
MainThreadErrors: createMainId<MainThreadErrorsShape>('MainThreadErrors', MainThreadErrorsShape),
MainThreadTreeViews: createMainId<MainThreadTreeViewsShape>('MainThreadTreeViews', MainThreadTreeViewsShape),
MainThreadLanguageFeatures: createMainId<MainThreadLanguageFeaturesShape>('MainThreadLanguageFeatures', MainThreadLanguageFeaturesShape),
MainThreadLanguages: createMainId<MainThreadLanguagesShape>('MainThreadLanguages', MainThreadLanguagesShape),
MainThreadMessageService: createMainId<MainThreadMessageServiceShape>('MainThreadMessageService', MainThreadMessageServiceShape),
MainThreadOutputService: createMainId<MainThreadOutputServiceShape>('MainThreadOutputService', MainThreadOutputServiceShape),
MainThreadProgress: createMainId<MainThreadProgressShape>('MainThreadProgress', MainThreadProgressShape),
MainThreadQuickOpen: createMainId<MainThreadQuickOpenShape>('MainThreadQuickOpen', MainThreadQuickOpenShape),
MainThreadStatusBar: createMainId<MainThreadStatusBarShape>('MainThreadStatusBar', MainThreadStatusBarShape),
MainThreadStorage: createMainId<MainThreadStorageShape>('MainThreadStorage', MainThreadStorageShape),
MainThreadTelemetry: createMainId<MainThreadTelemetryShape>('MainThreadTelemetry', MainThreadTelemetryShape),
MainThreadTerminalService: createMainId<MainThreadTerminalServiceShape>('MainThreadTerminalService', MainThreadTerminalServiceShape),
MainThreadWorkspace: createMainId<MainThreadWorkspaceShape>('MainThreadWorkspace', MainThreadWorkspaceShape),
MainProcessExtensionService: createMainId<MainProcessExtensionServiceShape>('MainProcessExtensionService', MainProcessExtensionServiceShape),
MainThreadSCM: createMainId<MainThreadSCMShape>('MainThreadSCM', MainThreadSCMShape),
MainThreadTask: createMainId<MainThreadTaskShape>('MainThreadTask', MainThreadTaskShape),
MainThreadCredentials: createMainId<MainThreadCredentialsShape>('MainThreadCredentials', MainThreadCredentialsShape),
MainThreadWindow: createMainId<MainThreadWindowShape>('MainThreadWindow', MainThreadWindowShape),
MainThreadCommands: createMainId<MainThreadCommandsShape>('MainThreadCommands'),
MainThreadConfiguration: createMainId<MainThreadConfigurationShape>('MainThreadConfiguration'),
MainThreadDebugService: createMainId<MainThreadDebugServiceShape>('MainThreadDebugService'),
MainThreadDiagnostics: createMainId<MainThreadDiagnosticsShape>('MainThreadDiagnostics'),
MainThreadDialogs: createMainId<MainThreadDiaglogsShape>('MainThreadDiaglogs'),
MainThreadDocuments: createMainId<MainThreadDocumentsShape>('MainThreadDocuments'),
MainThreadDocumentContentProviders: createMainId<MainThreadDocumentContentProvidersShape>('MainThreadDocumentContentProviders'),
MainThreadEditors: createMainId<MainThreadEditorsShape>('MainThreadEditors'),
MainThreadErrors: createMainId<MainThreadErrorsShape>('MainThreadErrors'),
MainThreadTreeViews: createMainId<MainThreadTreeViewsShape>('MainThreadTreeViews'),
MainThreadLanguageFeatures: createMainId<MainThreadLanguageFeaturesShape>('MainThreadLanguageFeatures'),
MainThreadLanguages: createMainId<MainThreadLanguagesShape>('MainThreadLanguages'),
MainThreadMessageService: createMainId<MainThreadMessageServiceShape>('MainThreadMessageService'),
MainThreadOutputService: createMainId<MainThreadOutputServiceShape>('MainThreadOutputService'),
MainThreadProgress: createMainId<MainThreadProgressShape>('MainThreadProgress'),
MainThreadQuickOpen: createMainId<MainThreadQuickOpenShape>('MainThreadQuickOpen'),
MainThreadStatusBar: createMainId<MainThreadStatusBarShape>('MainThreadStatusBar'),
MainThreadStorage: createMainId<MainThreadStorageShape>('MainThreadStorage'),
MainThreadTelemetry: createMainId<MainThreadTelemetryShape>('MainThreadTelemetry'),
MainThreadTerminalService: createMainId<MainThreadTerminalServiceShape>('MainThreadTerminalService'),
MainThreadWorkspace: createMainId<MainThreadWorkspaceShape>('MainThreadWorkspace'),
MainThreadExtensionService: createMainId<MainThreadExtensionServiceShape>('MainThreadExtensionService'),
MainThreadSCM: createMainId<MainThreadSCMShape>('MainThreadSCM'),
MainThreadTask: createMainId<MainThreadTaskShape>('MainThreadTask'),
MainThreadCredentials: createMainId<MainThreadCredentialsShape>('MainThreadCredentials'),
MainThreadWindow: createMainId<MainThreadWindowShape>('MainThreadWindow'),
};
export const ExtHostContext = {
ExtHostCommands: createExtId<ExtHostCommandsShape>('ExtHostCommands', ExtHostCommandsShape),
ExtHostConfiguration: createExtId<ExtHostConfigurationShape>('ExtHostConfiguration', ExtHostConfigurationShape),
ExtHostDiagnostics: createExtId<ExtHostDiagnosticsShape>('ExtHostDiagnostics', ExtHostDiagnosticsShape),
ExtHostDebugService: createExtId<ExtHostDebugServiceShape>('ExtHostDebugService', ExtHostDebugServiceShape),
ExtHostDocumentsAndEditors: createExtId<ExtHostDocumentsAndEditorsShape>('ExtHostDocumentsAndEditors', ExtHostDocumentsAndEditorsShape),
ExtHostDocuments: createExtId<ExtHostDocumentsShape>('ExtHostDocuments', ExtHostDocumentsShape),
ExtHostDocumentSaveParticipant: createExtId<ExtHostDocumentSaveParticipantShape>('ExtHostDocumentSaveParticipant', ExtHostDocumentSaveParticipantShape),
ExtHostEditors: createExtId<ExtHostEditorsShape>('ExtHostEditors', ExtHostEditorsShape),
ExtHostTreeViews: createExtId<ExtHostTreeViewsShape>('ExtHostTreeViews', ExtHostTreeViewsShape),
ExtHostFileSystemEventService: createExtId<ExtHostFileSystemEventServiceShape>('ExtHostFileSystemEventService', ExtHostFileSystemEventServiceShape),
ExtHostHeapService: createExtId<ExtHostHeapServiceShape>('ExtHostHeapMonitor', ExtHostHeapServiceShape),
ExtHostLanguageFeatures: createExtId<ExtHostLanguageFeaturesShape>('ExtHostLanguageFeatures', ExtHostLanguageFeaturesShape),
ExtHostQuickOpen: createExtId<ExtHostQuickOpenShape>('ExtHostQuickOpen', ExtHostQuickOpenShape),
ExtHostExtensionService: createExtId<ExtHostExtensionServiceShape>('ExtHostExtensionService', ExtHostExtensionServiceShape),
ExtHostTerminalService: createExtId<ExtHostTerminalServiceShape>('ExtHostTerminalService', ExtHostTerminalServiceShape),
ExtHostSCM: createExtId<ExtHostSCMShape>('ExtHostSCM', ExtHostSCMShape),
ExtHostTask: createExtId<ExtHostTaskShape>('ExtHostTask', ExtHostTaskShape),
ExtHostWorkspace: createExtId<ExtHostWorkspaceShape>('ExtHostWorkspace', ExtHostWorkspaceShape),
ExtHostCredentials: createExtId<ExtHostCredentialsShape>('ExtHostCredentials', ExtHostCredentialsShape),
ExtHostWindow: createExtId<ExtHostWindowShape>('ExtHostWindow', ExtHostWindowShape),
ExtHostCommands: createExtId<ExtHostCommandsShape>('ExtHostCommands'),
ExtHostConfiguration: createExtId<ExtHostConfigurationShape>('ExtHostConfiguration'),
ExtHostDiagnostics: createExtId<ExtHostDiagnosticsShape>('ExtHostDiagnostics'),
ExtHostDebugService: createExtId<ExtHostDebugServiceShape>('ExtHostDebugService'),
ExtHostDocumentsAndEditors: createExtId<ExtHostDocumentsAndEditorsShape>('ExtHostDocumentsAndEditors'),
ExtHostDocuments: createExtId<ExtHostDocumentsShape>('ExtHostDocuments'),
ExtHostDocumentContentProviders: createExtId<ExtHostDocumentContentProvidersShape>('ExtHostDocumentContentProviders'),
ExtHostDocumentSaveParticipant: createExtId<ExtHostDocumentSaveParticipantShape>('ExtHostDocumentSaveParticipant'),
ExtHostEditors: createExtId<ExtHostEditorsShape>('ExtHostEditors'),
ExtHostTreeViews: createExtId<ExtHostTreeViewsShape>('ExtHostTreeViews'),
ExtHostFileSystemEventService: createExtId<ExtHostFileSystemEventServiceShape>('ExtHostFileSystemEventService'),
ExtHostHeapService: createExtId<ExtHostHeapServiceShape>('ExtHostHeapMonitor'),
ExtHostLanguageFeatures: createExtId<ExtHostLanguageFeaturesShape>('ExtHostLanguageFeatures'),
ExtHostQuickOpen: createExtId<ExtHostQuickOpenShape>('ExtHostQuickOpen'),
ExtHostExtensionService: createExtId<ExtHostExtensionServiceShape>('ExtHostExtensionService'),
ExtHostTerminalService: createExtId<ExtHostTerminalServiceShape>('ExtHostTerminalService'),
ExtHostSCM: createExtId<ExtHostSCMShape>('ExtHostSCM'),
ExtHostTask: createExtId<ExtHostTaskShape>('ExtHostTask'),
ExtHostWorkspace: createExtId<ExtHostWorkspaceShape>('ExtHostWorkspace'),
ExtHostCredentials: createExtId<ExtHostCredentialsShape>('ExtHostCredentials'),
ExtHostWindow: createExtId<ExtHostWindowShape>('ExtHostWindow'),
};

View File

@@ -195,8 +195,8 @@ export class ExtHostApiCommands {
]
});
this._register('vscode.startDebug', (configuration?: any) => {
return this._commands.executeCommand('_workbench.startDebug', configuration);
this._register('vscode.startDebug', (configuration?: any, folderUri?: URI) => {
return this._commands.executeCommand('_workbench.startDebug', configuration, folderUri);
}, {
description: 'Start a debugging session.',
args: [
@@ -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' }

View File

@@ -4,14 +4,13 @@
*--------------------------------------------------------------------------------------------*/
'use strict';
import { IThreadService } from 'vs/workbench/services/thread/common/threadService';
import { validateConstraint } from 'vs/base/common/types';
import { ICommandHandlerDescription } from 'vs/platform/commands/common/commands';
import { TPromise } from 'vs/base/common/winjs.base';
import * as extHostTypes from 'vs/workbench/api/node/extHostTypes';
import * as extHostTypeConverter from 'vs/workbench/api/node/extHostTypeConverters';
import { cloneAndChange } from 'vs/base/common/objects';
import { MainContext, MainThreadCommandsShape, ExtHostCommandsShape, ObjectIdentifier } from './extHost.protocol';
import { MainContext, MainThreadCommandsShape, ExtHostCommandsShape, ObjectIdentifier, IMainContext } from './extHost.protocol';
import { ExtHostHeapService } from 'vs/workbench/api/node/extHostHeapService';
import { isFalsyOrEmpty } from 'vs/base/common/arrays';
import * as modes from 'vs/editor/common/modes';
@@ -27,7 +26,7 @@ export interface ArgumentProcessor {
processArgument(arg: any): any;
}
export class ExtHostCommands extends ExtHostCommandsShape {
export class ExtHostCommands implements ExtHostCommandsShape {
private _commands = new Map<string, CommandHandler>();
private _proxy: MainThreadCommandsShape;
@@ -35,11 +34,10 @@ export class ExtHostCommands extends ExtHostCommandsShape {
private _argumentProcessors: ArgumentProcessor[] = [];
constructor(
threadService: IThreadService,
mainContext: IMainContext,
heapService: ExtHostHeapService
) {
super();
this._proxy = threadService.get(MainContext.MainThreadCommands);
this._proxy = mainContext.get(MainContext.MainThreadCommands);
this._converter = new CommandsConverter(this, heapService);
}
@@ -58,7 +56,7 @@ export class ExtHostCommands extends ExtHostCommandsShape {
}
if (this._commands.has(id)) {
throw new Error('command with id already exists');
throw new Error(`command '${id}' already exists`);
}
this._commands.set(id, { callback, thisArg, description });

View File

@@ -7,9 +7,10 @@
import { mixin } from 'vs/base/common/objects';
import URI from 'vs/base/common/uri';
import Event, { Emitter } from 'vs/base/common/event';
import { WorkspaceConfiguration, WorkspaceConfiguration2 } from 'vscode';
import { WorkspaceConfiguration } from 'vscode';
import { ExtHostWorkspace } from 'vs/workbench/api/node/extHostWorkspace';
import { ExtHostConfigurationShape, MainThreadConfigurationShape } from './extHost.protocol';
import { ConfigurationTarget as ExtHostConfigurationTarget } from './extHostTypes';
import { IConfigurationData, Configuration } from 'vs/platform/configuration/common/configuration';
import { ConfigurationTarget } from 'vs/workbench/services/configuration/common/configurationEditing';
@@ -29,10 +30,10 @@ type ConfigurationInspect<T> = {
defaultValue?: T;
globalValue?: T;
workspaceValue?: T;
folderValue?: T;
workspaceFolderValue?: T;
};
export class ExtHostConfiguration extends ExtHostConfigurationShape {
export class ExtHostConfiguration implements ExtHostConfigurationShape {
private readonly _onDidChangeConfiguration = new Emitter<void>();
private readonly _proxy: MainThreadConfigurationShape;
@@ -40,7 +41,6 @@ export class ExtHostConfiguration extends ExtHostConfigurationShape {
private _configuration: Configuration<any>;
constructor(proxy: MainThreadConfigurationShape, extHostWorkspace: ExtHostWorkspace, data: IConfigurationData<any>) {
super();
this._proxy = proxy;
this._extHostWorkspace = extHostWorkspace;
this._configuration = Configuration.parse(data, extHostWorkspace.workspace);
@@ -55,20 +55,26 @@ export class ExtHostConfiguration extends ExtHostConfigurationShape {
this._onDidChangeConfiguration.fire(undefined);
}
getConfiguration(section?: string): WorkspaceConfiguration {
return this._getConfiguration(section, null, true);
}
getConfiguration2(section?: string, resource?: URI): WorkspaceConfiguration2 {
return this._getConfiguration(section, resource, false);
}
private _getConfiguration(section: string, resource: URI, legacy: boolean): WorkspaceConfiguration {
getConfiguration(section?: string, resource?: URI): WorkspaceConfiguration {
const config = section
? lookUp(this._configuration.getValue(null, { resource }), section)
: this._configuration.getValue(null, { resource });
function parseConfigurationTarget(arg: boolean | ExtHostConfigurationTarget): ConfigurationTarget {
if (arg === void 0 || arg === null) {
return null;
}
if (typeof arg === 'boolean') {
return arg ? ConfigurationTarget.USER : ConfigurationTarget.WORKSPACE;
}
switch (arg) {
case ExtHostConfigurationTarget.Global: return ConfigurationTarget.USER;
case ExtHostConfigurationTarget.Workspace: return ConfigurationTarget.WORKSPACE;
case ExtHostConfigurationTarget.WorkspaceFolder: return ConfigurationTarget.FOLDER;
}
}
const result: WorkspaceConfiguration = {
has(key: string): boolean {
return typeof lookUp(config, key) !== 'undefined';
@@ -80,29 +86,26 @@ export class ExtHostConfiguration extends ExtHostConfigurationShape {
}
return result;
},
update: (key: string, value: any, global: boolean = false) => {
update: (key: string, value: any, arg: ExtHostConfigurationTarget | boolean) => {
key = section ? `${section}.${key}` : key;
const target = global ? ConfigurationTarget.USER : ConfigurationTarget.WORKSPACE;
const target = parseConfigurationTarget(arg);
if (value !== void 0) {
return this._proxy.$updateConfigurationOption(target, key, value);
return this._proxy.$updateConfigurationOption(target, key, value, resource);
} else {
return this._proxy.$removeConfigurationOption(target, key);
return this._proxy.$removeConfigurationOption(target, key, resource);
}
},
inspect: <T>(key: string): ConfigurationInspect<T> => {
key = section ? `${section}.${key}` : key;
const config = legacy ? this._configuration.lookupLegacy<T>(key) : this._configuration.lookup<T>(key, { resource });
const config = this._configuration.lookup<T>(key, { resource });
if (config) {
const inspect: ConfigurationInspect<T> = {
return {
key,
defaultValue: config.default,
globalValue: config.user,
workspaceValue: config.workspace,
workspaceFolderValue: config.folder
};
if (!legacy) {
inspect.folderValue = config.folder;
}
return inspect;
}
return undefined;
}

View File

@@ -4,17 +4,15 @@
*--------------------------------------------------------------------------------------------*/
'use strict';
import { MainContext, MainThreadCredentialsShape, ExtHostCredentialsShape } from 'vs/workbench/api/node/extHost.protocol';
import { IThreadService } from 'vs/workbench/services/thread/common/threadService';
import { MainContext, MainThreadCredentialsShape, ExtHostCredentialsShape, IMainContext } from 'vs/workbench/api/node/extHost.protocol';
export class ExtHostCredentials extends ExtHostCredentialsShape {
export class ExtHostCredentials implements ExtHostCredentialsShape {
private _proxy: MainThreadCredentialsShape;
constructor(threadService: IThreadService) {
super();
this._proxy = threadService.get(MainContext.MainThreadCredentials);
constructor(mainContext: IMainContext) {
this._proxy = mainContext.get(MainContext.MainThreadCredentials);
};
readSecret(service: string, account: string): Thenable<string | undefined> {

View File

@@ -6,14 +6,21 @@
import { TPromise } from 'vs/base/common/winjs.base';
import Event, { Emitter } from 'vs/base/common/event';
import { IThreadService } from 'vs/workbench/services/thread/common/threadService';
import { MainContext, MainThreadDebugServiceShape, ExtHostDebugServiceShape, DebugSessionUUID } from 'vs/workbench/api/node/extHost.protocol';
import { asWinJsPromise } from 'vs/base/common/async';
import { MainContext, MainThreadDebugServiceShape, ExtHostDebugServiceShape, DebugSessionUUID, IMainContext } from 'vs/workbench/api/node/extHost.protocol';
import { ExtHostWorkspace } from 'vs/workbench/api/node/extHostWorkspace';
import * as vscode from 'vscode';
import URI from 'vs/base/common/uri';
import * as types from 'vs/workbench/api/node/extHostTypes';
export class ExtHostDebugService extends ExtHostDebugServiceShape {
export class ExtHostDebugService implements ExtHostDebugServiceShape {
private _workspace: ExtHostWorkspace;
private _handleCounter: number;
private _handlers: Map<number, vscode.DebugConfigurationProvider>;
private _debugServiceProxy: MainThreadDebugServiceShape;
private _debugSessions: Map<DebugSessionUUID, ExtHostDebugSession> = new Map<DebugSessionUUID, ExtHostDebugSession>();
@@ -34,25 +41,67 @@ export class ExtHostDebugService extends ExtHostDebugServiceShape {
get onDidReceiveDebugSessionCustomEvent(): Event<vscode.DebugSessionCustomEvent> { return this._onDidReceiveDebugSessionCustomEvent.event; }
constructor(threadService: IThreadService) {
super();
constructor(mainContext: IMainContext, workspace: ExtHostWorkspace) {
this._workspace = workspace;
this._handleCounter = 0;
this._handlers = new Map<number, vscode.DebugConfigurationProvider>();
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);
this._debugServiceProxy = mainContext.get(MainContext.MainThreadDebugService);
}
public startDebugging(nameOrConfig: string | vscode.DebugConfiguration): TPromise<boolean> {
public registerDebugConfigurationProvider(type: string, provider: vscode.DebugConfigurationProvider): vscode.Disposable {
if (!provider) {
return new types.Disposable(() => { });
}
return this._debugServiceProxy.$startDebugging(nameOrConfig);
let handle = this.nextHandle();
this._handlers.set(handle, provider);
this._debugServiceProxy.$registerDebugConfigurationProvider(type, !!provider.provideDebugConfigurations, !!provider.resolveDebugConfiguration, handle);
return new types.Disposable(() => {
this._handlers.delete(handle);
this._debugServiceProxy.$unregisterDebugConfigurationProvider(handle);
});
}
public startDebugSession(config: vscode.DebugConfiguration): TPromise<vscode.DebugSession> {
public $provideDebugConfigurations(handle: number, folderUri: URI | undefined): TPromise<vscode.DebugConfiguration[]> {
let handler = this._handlers.get(handle);
if (!handler) {
return TPromise.wrapError<vscode.DebugConfiguration[]>(new Error('no handler found'));
}
if (!handler.provideDebugConfigurations) {
return TPromise.wrapError<vscode.DebugConfiguration[]>(new Error('handler has no method provideDebugConfigurations'));
}
return asWinJsPromise(token => handler.provideDebugConfigurations(this.getFolder(folderUri), token));
}
return this._debugServiceProxy.$startDebugSession(config).then((id: DebugSessionUUID) => {
public $resolveDebugConfiguration(handle: number, folderUri: URI | undefined, debugConfiguration: vscode.DebugConfiguration): TPromise<vscode.DebugConfiguration> {
let handler = this._handlers.get(handle);
if (!handler) {
return TPromise.wrapError<vscode.DebugConfiguration>(new Error('no handler found'));
}
if (!handler.resolveDebugConfiguration) {
return TPromise.wrapError<vscode.DebugConfiguration>(new Error('handler has no method resolveDebugConfiguration'));
}
return asWinJsPromise(token => handler.resolveDebugConfiguration(this.getFolder(folderUri), debugConfiguration, token));
}
public startDebugging(folder: vscode.WorkspaceFolder | undefined, nameOrConfig: string | vscode.DebugConfiguration): TPromise<boolean> {
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;
@@ -108,6 +157,21 @@ export class ExtHostDebugService extends ExtHostDebugServiceShape {
};
this._onDidReceiveDebugSessionCustomEvent.fire(ee);
}
private getFolder(folderUri: URI | undefined) {
if (folderUri) {
const folders = this._workspace.getWorkspaceFolders();
const found = folders.filter(f => f.uri.toString() === folderUri.toString());
if (found && found.length > 0) {
return found[0];
}
}
return undefined;
}
private nextHandle(): number {
return this._handleCounter++;
}
}
export class ExtHostDebugSession implements vscode.DebugSession {

View File

@@ -5,12 +5,11 @@
'use strict';
import { localize } from 'vs/nls';
import { IThreadService } from 'vs/workbench/services/thread/common/threadService';
import { IMarkerData } from 'vs/platform/markers/common/markers';
import URI from 'vs/base/common/uri';
import Severity from 'vs/base/common/severity';
import * as vscode from 'vscode';
import { MainContext, MainThreadDiagnosticsShape, ExtHostDiagnosticsShape } from './extHost.protocol';
import { MainContext, MainThreadDiagnosticsShape, ExtHostDiagnosticsShape, IMainContext } from './extHost.protocol';
import { DiagnosticSeverity } from './extHostTypes';
import { mergeSort } from 'vs/base/common/arrays';
@@ -217,16 +216,15 @@ export class DiagnosticCollection implements vscode.DiagnosticCollection {
}
}
export class ExtHostDiagnostics extends ExtHostDiagnosticsShape {
export class ExtHostDiagnostics implements ExtHostDiagnosticsShape {
private static _idPool: number = 0;
private _proxy: MainThreadDiagnosticsShape;
private _collections: DiagnosticCollection[];
constructor(threadService: IThreadService) {
super();
this._proxy = threadService.get(MainContext.MainThreadDiagnostics);
constructor(mainContext: IMainContext) {
this._proxy = mainContext.get(MainContext.MainThreadDiagnostics);
this._collections = [];
}

View File

@@ -0,0 +1,24 @@
/*---------------------------------------------------------------------------------------------
* 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 * as vscode from 'vscode';
import URI from 'vs/base/common/uri';
import { MainContext, MainThreadDiaglogsShape, IMainContext } from 'vs/workbench/api/node/extHost.protocol';
export class ExtHostDialogs {
private readonly _proxy: MainThreadDiaglogsShape;
constructor(mainContext: IMainContext) {
this._proxy = mainContext.get(MainContext.MainThreadDialogs);
}
showOpenDialog(options: vscode.OpenDialogOptions): Thenable<URI[]> {
return this._proxy.$showOpenDialog(<any>options).then(filepaths => {
return filepaths && filepaths.map(URI.file);
});
}
}

View File

@@ -0,0 +1,88 @@
/*---------------------------------------------------------------------------------------------
* 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 { onUnexpectedError } from 'vs/base/common/errors';
import * as editorCommon from 'vs/editor/common/editorCommon';
import URI from 'vs/base/common/uri';
import { IDisposable } from 'vs/base/common/lifecycle';
import { Disposable } from 'vs/workbench/api/node/extHostTypes';
import { TPromise } from 'vs/base/common/winjs.base';
import * as vscode from 'vscode';
import { asWinJsPromise } from 'vs/base/common/async';
import { TextSource } from 'vs/editor/common/model/textSource';
import { MainContext, ExtHostDocumentContentProvidersShape, MainThreadDocumentContentProvidersShape, IMainContext } from './extHost.protocol';
import { ExtHostDocumentsAndEditors } from './extHostDocumentsAndEditors';
export class ExtHostDocumentContentProvider implements ExtHostDocumentContentProvidersShape {
private static _handlePool = 0;
private readonly _documentContentProviders = new Map<number, vscode.TextDocumentContentProvider>();
private readonly _proxy: MainThreadDocumentContentProvidersShape;
private readonly _documentsAndEditors: ExtHostDocumentsAndEditors;
constructor(mainContext: IMainContext, documentsAndEditors: ExtHostDocumentsAndEditors) {
this._proxy = mainContext.get(MainContext.MainThreadDocumentContentProviders);
this._documentsAndEditors = documentsAndEditors;
}
dispose(): void {
// todo@joh
}
registerTextDocumentContentProvider(scheme: string, provider: vscode.TextDocumentContentProvider): vscode.Disposable {
if (scheme === 'file' || scheme === 'untitled') {
throw new Error(`scheme '${scheme}' already registered`);
}
const handle = ExtHostDocumentContentProvider._handlePool++;
this._documentContentProviders.set(handle, provider);
this._proxy.$registerTextContentProvider(handle, scheme);
let subscription: IDisposable;
if (typeof provider.onDidChange === 'function') {
subscription = provider.onDidChange(uri => {
if (this._documentsAndEditors.getDocument(uri.toString())) {
this.$provideTextDocumentContent(handle, <URI>uri).then(value => {
const document = this._documentsAndEditors.getDocument(uri.toString());
if (!document) {
// disposed in the meantime
return;
}
// create lines and compare
const textSource = TextSource.fromString(value, editorCommon.DefaultEndOfLine.CRLF);
// broadcast event when content changed
if (!document.equalLines(textSource)) {
return this._proxy.$onVirtualDocumentChange(<URI>uri, textSource);
}
}, onUnexpectedError);
}
});
}
return new Disposable(() => {
if (this._documentContentProviders.delete(handle)) {
this._proxy.$unregisterTextContentProvider(handle);
}
if (subscription) {
subscription.dispose();
subscription = undefined;
}
});
}
$provideTextDocumentContent(handle: number, uri: URI): TPromise<string> {
const provider = this._documentContentProviders.get(handle);
if (!provider) {
return TPromise.wrapError<string>(new Error(`unsupported uri-scheme: ${uri.scheme}`));
}
return asWinJsPromise(token => provider.provideTextDocumentContent(uri, token));
}
}

View File

@@ -18,7 +18,7 @@ import { ExtHostDocuments } from 'vs/workbench/api/node/extHostDocuments';
import { SaveReason } from 'vs/workbench/services/textfile/common/textfiles';
import * as vscode from 'vscode';
export class ExtHostDocumentSaveParticipant extends ExtHostDocumentSaveParticipantShape {
export class ExtHostDocumentSaveParticipant implements ExtHostDocumentSaveParticipantShape {
private _documents: ExtHostDocuments;
private _workspace: MainThreadWorkspaceShape;
@@ -27,7 +27,6 @@ export class ExtHostDocumentSaveParticipant extends ExtHostDocumentSaveParticipa
private _thresholds: { timeout: number; errors: number; };
constructor(documents: ExtHostDocuments, workspace: MainThreadWorkspaceShape, thresholds: { timeout: number; errors: number; } = { timeout: 1500, errors: 3 }) {
super();
this._documents = documents;
this._workspace = workspace;
this._thresholds = thresholds;
@@ -149,7 +148,7 @@ export class ExtHostDocumentSaveParticipant extends ExtHostDocumentSaveParticipa
}
}
// apply edits iff any and iff document
// apply edits if any and if document
// didn't change somehow in the meantime
if (edits.length === 0) {
return undefined;

View File

@@ -4,26 +4,18 @@
*--------------------------------------------------------------------------------------------*/
'use strict';
import { onUnexpectedError } from 'vs/base/common/errors';
import * as editorCommon from 'vs/editor/common/editorCommon';
import { IThreadService } from 'vs/workbench/services/thread/common/threadService';
import Event, { Emitter } from 'vs/base/common/event';
import URI from 'vs/base/common/uri';
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
import { Disposable } from 'vs/workbench/api/node/extHostTypes';
import * as TypeConverters from './extHostTypeConverters';
import { TPromise } from 'vs/base/common/winjs.base';
import * as vscode from 'vscode';
import { asWinJsPromise } from 'vs/base/common/async';
import { TextSource } from 'vs/editor/common/model/textSource';
import { MainContext, MainThreadDocumentsShape, ExtHostDocumentsShape } from './extHost.protocol';
import { MainContext, MainThreadDocumentsShape, ExtHostDocumentsShape, IMainContext } from './extHost.protocol';
import { ExtHostDocumentData, setWordDefinitionFor } from './extHostDocumentData';
import { ExtHostDocumentsAndEditors } from './extHostDocumentsAndEditors';
import { IModelChangedEvent } from 'vs/editor/common/model/mirrorModel';
export class ExtHostDocuments extends ExtHostDocumentsShape {
private static _handlePool: number = 0;
export class ExtHostDocuments implements ExtHostDocumentsShape {
private _onDidAddDocument = new Emitter<vscode.TextDocument>();
private _onDidRemoveDocument = new Emitter<vscode.TextDocument>();
@@ -39,12 +31,9 @@ export class ExtHostDocuments extends ExtHostDocumentsShape {
private _proxy: MainThreadDocumentsShape;
private _documentsAndEditors: ExtHostDocumentsAndEditors;
private _documentLoader = new Map<string, TPromise<ExtHostDocumentData>>();
private _documentContentProviders = new Map<number, vscode.TextDocumentContentProvider>();
constructor(threadService: IThreadService, documentsAndEditors: ExtHostDocumentsAndEditors) {
super();
this._proxy = threadService.get(MainContext.MainThreadDocuments);
constructor(mainContext: IMainContext, documentsAndEditors: ExtHostDocumentsAndEditors) {
this._proxy = mainContext.get(MainContext.MainThreadDocuments);
this._documentsAndEditors = documentsAndEditors;
this._toDispose = [
@@ -106,59 +95,6 @@ export class ExtHostDocuments extends ExtHostDocumentsShape {
return this._proxy.$tryCreateDocument(options);
}
public registerTextDocumentContentProvider(scheme: string, provider: vscode.TextDocumentContentProvider): vscode.Disposable {
if (scheme === 'file' || scheme === 'untitled') {
throw new Error(`scheme '${scheme}' already registered`);
}
const handle = ExtHostDocuments._handlePool++;
this._documentContentProviders.set(handle, provider);
this._proxy.$registerTextContentProvider(handle, scheme);
let subscription: IDisposable;
if (typeof provider.onDidChange === 'function') {
subscription = provider.onDidChange(uri => {
if (this._documentsAndEditors.getDocument(uri.toString())) {
this.$provideTextDocumentContent(handle, <URI>uri).then(value => {
const document = this._documentsAndEditors.getDocument(uri.toString());
if (!document) {
// disposed in the meantime
return;
}
// create lines and compare
const textSource = TextSource.fromString(value, editorCommon.DefaultEndOfLine.CRLF);
// broadcast event when content changed
if (!document.equalLines(textSource)) {
return this._proxy.$onVirtualDocumentChange(<URI>uri, textSource);
}
}, onUnexpectedError);
}
});
}
return new Disposable(() => {
if (this._documentContentProviders.delete(handle)) {
this._proxy.$unregisterTextContentProvider(handle);
}
if (subscription) {
subscription.dispose();
subscription = undefined;
}
});
}
public $provideTextDocumentContent(handle: number, uri: URI): TPromise<string> {
const provider = this._documentContentProviders.get(handle);
if (!provider) {
return TPromise.wrapError<string>(new Error(`unsupported uri-scheme: ${uri.scheme}`));
}
return asWinJsPromise(token => provider.provideTextDocumentContent(uri, token));
}
public $acceptModelModeChanged(strURL: string, oldModeId: string, newModeId: string): void {
let data = this._documentsAndEditors.getDocument(strURL);

View File

@@ -6,14 +6,14 @@
import Event, { Emitter } from 'vs/base/common/event';
import { dispose } from 'vs/base/common/lifecycle';
import { MainContext, ExtHostDocumentsAndEditorsShape, IDocumentsAndEditorsDelta } from './extHost.protocol';
import { MainContext, ExtHostDocumentsAndEditorsShape, IDocumentsAndEditorsDelta, IMainContext } from './extHost.protocol';
import { ExtHostDocumentData } from './extHostDocumentData';
import { ExtHostTextEditor } from './extHostTextEditor';
import { IThreadService } from 'vs/workbench/services/thread/common/threadService';
import { ExtHostTextEditor, ExtHostTextEditor2 } from './extHostTextEditor';
import * as assert from 'assert';
import * as typeConverters from './extHostTypeConverters';
import { ExtHostExtensionService } from 'vs/workbench/api/node/extHostExtensionService';
export class ExtHostDocumentsAndEditors extends ExtHostDocumentsAndEditorsShape {
export class ExtHostDocumentsAndEditors implements ExtHostDocumentsAndEditorsShape {
private _activeEditorId: string;
private readonly _editors = new Map<string, ExtHostTextEditor>();
@@ -30,9 +30,9 @@ export class ExtHostDocumentsAndEditors extends ExtHostDocumentsAndEditorsShape
readonly onDidChangeActiveTextEditor: Event<ExtHostTextEditor> = this._onDidChangeActiveTextEditor.event;
constructor(
@IThreadService private _threadService: IThreadService
private readonly _mainContext: IMainContext,
private readonly _extHostExtensions?: ExtHostExtensionService
) {
super();
}
$acceptDocumentsAndEditorsDelta(delta: IDocumentsAndEditorsDelta): void {
@@ -54,7 +54,7 @@ export class ExtHostDocumentsAndEditors extends ExtHostDocumentsAndEditorsShape
assert.ok(!this._documents.has(data.url.toString()), `document '${data.url} already exists!'`);
const documentData = new ExtHostDocumentData(
this._threadService.get(MainContext.MainThreadDocuments),
this._mainContext.get(MainContext.MainThreadDocuments),
data.url,
data.lines,
data.EOL,
@@ -81,8 +81,10 @@ export class ExtHostDocumentsAndEditors extends ExtHostDocumentsAndEditorsShape
assert.ok(!this._editors.has(data.id), `editor '${data.id}' already exists!`);
const documentData = this._documents.get(data.document.toString());
const editor = new ExtHostTextEditor(
this._threadService.get(MainContext.MainThreadEditors),
const editor = new ExtHostTextEditor2(
this._extHostExtensions,
this._mainContext.get(MainContext.MainThreadTelemetry),
this._mainContext.get(MainContext.MainThreadEditors),
data.id,
documentData,
data.selections.map(typeConverters.toSelection),

View File

@@ -0,0 +1,327 @@
/*---------------------------------------------------------------------------------------------
* 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 * as nls from 'vs/nls';
import { IDisposable } from 'vs/base/common/lifecycle';
import Severity from 'vs/base/common/severity';
import { TPromise } from 'vs/base/common/winjs.base';
import { ExtensionDescriptionRegistry } from 'vs/workbench/services/extensions/node/extensionDescriptionRegistry';
import { IExtensionDescription } from 'vs/platform/extensions/common/extensions';
const hasOwnProperty = Object.hasOwnProperty;
const NO_OP_VOID_PROMISE = TPromise.as<void>(void 0);
export interface IExtensionMemento {
get<T>(key: string, defaultValue: T): T;
update(key: string, value: any): Thenable<boolean>;
}
export interface IExtensionContext {
subscriptions: IDisposable[];
workspaceState: IExtensionMemento;
globalState: IExtensionMemento;
extensionPath: string;
storagePath: string;
asAbsolutePath(relativePath: string): string;
}
/**
* Represents the source code (module) of an extension.
*/
export interface IExtensionModule {
activate(ctx: IExtensionContext): TPromise<IExtensionAPI>;
deactivate(): void;
}
/**
* Represents the API of an extension (return value of `activate`).
*/
export interface IExtensionAPI {
// _extensionAPIBrand: any;
}
export class ExtensionActivationTimes {
public static NONE = new ExtensionActivationTimes(false, -1, -1, -1);
public readonly startup: boolean;
public readonly codeLoadingTime: number;
public readonly activateCallTime: number;
public readonly activateResolvedTime: number;
constructor(startup: boolean, codeLoadingTime: number, activateCallTime: number, activateResolvedTime: number) {
this.startup = startup;
this.codeLoadingTime = codeLoadingTime;
this.activateCallTime = activateCallTime;
this.activateResolvedTime = activateResolvedTime;
}
}
export class ExtensionActivationTimesBuilder {
private readonly _startup: boolean;
private _codeLoadingStart: number;
private _codeLoadingStop: number;
private _activateCallStart: number;
private _activateCallStop: number;
private _activateResolveStart: number;
private _activateResolveStop: number;
constructor(startup: boolean) {
this._startup = startup;
this._codeLoadingStart = -1;
this._codeLoadingStop = -1;
this._activateCallStart = -1;
this._activateCallStop = -1;
this._activateResolveStart = -1;
this._activateResolveStop = -1;
}
private _delta(start: number, stop: number): number {
if (start === -1 || stop === -1) {
return -1;
}
return stop - start;
}
public build(): ExtensionActivationTimes {
return new ExtensionActivationTimes(
this._startup,
this._delta(this._codeLoadingStart, this._codeLoadingStop),
this._delta(this._activateCallStart, this._activateCallStop),
this._delta(this._activateResolveStart, this._activateResolveStop)
);
}
public codeLoadingStart(): void {
this._codeLoadingStart = Date.now();
}
public codeLoadingStop(): void {
this._codeLoadingStop = Date.now();
}
public activateCallStart(): void {
this._activateCallStart = Date.now();
}
public activateCallStop(): void {
this._activateCallStop = Date.now();
}
public activateResolveStart(): void {
this._activateResolveStart = Date.now();
}
public activateResolveStop(): void {
this._activateResolveStop = Date.now();
}
}
export class ActivatedExtension {
public readonly activationFailed: boolean;
public readonly activationTimes: ExtensionActivationTimes;
public readonly module: IExtensionModule;
public readonly exports: IExtensionAPI;
public readonly subscriptions: IDisposable[];
constructor(
activationFailed: boolean,
activationTimes: ExtensionActivationTimes,
module: IExtensionModule,
exports: IExtensionAPI,
subscriptions: IDisposable[]
) {
this.activationFailed = activationFailed;
this.activationTimes = activationTimes;
this.module = module;
this.exports = exports;
this.subscriptions = subscriptions;
}
}
export class EmptyExtension extends ActivatedExtension {
constructor(activationTimes: ExtensionActivationTimes) {
super(false, activationTimes, { activate: undefined, deactivate: undefined }, undefined, []);
}
}
export class FailedExtension extends ActivatedExtension {
constructor(activationTimes: ExtensionActivationTimes) {
super(true, activationTimes, { activate: undefined, deactivate: undefined }, undefined, []);
}
}
export interface IExtensionsActivatorHost {
showMessage(severity: Severity, message: string): void;
actualActivateExtension(extensionDescription: IExtensionDescription, startup: boolean): TPromise<ActivatedExtension>;
}
export class ExtensionsActivator {
private readonly _registry: ExtensionDescriptionRegistry;
private readonly _host: IExtensionsActivatorHost;
private readonly _activatingExtensions: { [extensionId: string]: TPromise<void>; };
private readonly _activatedExtensions: { [extensionId: string]: ActivatedExtension; };
/**
* A map of already activated events to speed things up if the same activation event is triggered multiple times.
*/
private readonly _alreadyActivatedEvents: { [activationEvent: string]: boolean; };
constructor(registry: ExtensionDescriptionRegistry, host: IExtensionsActivatorHost) {
this._registry = registry;
this._host = host;
this._activatingExtensions = {};
this._activatedExtensions = {};
this._alreadyActivatedEvents = Object.create(null);
}
public isActivated(extensionId: string): boolean {
return hasOwnProperty.call(this._activatedExtensions, extensionId);
}
public getActivatedExtension(extensionId: string): ActivatedExtension {
if (!hasOwnProperty.call(this._activatedExtensions, extensionId)) {
throw new Error('Extension `' + extensionId + '` is not known or not activated');
}
return this._activatedExtensions[extensionId];
}
public activateByEvent(activationEvent: string, startup: boolean): TPromise<void> {
if (this._alreadyActivatedEvents[activationEvent]) {
return NO_OP_VOID_PROMISE;
}
let activateExtensions = this._registry.getExtensionDescriptionsForActivationEvent(activationEvent);
return this._activateExtensions(activateExtensions, startup, 0).then(() => {
this._alreadyActivatedEvents[activationEvent] = true;
});
}
public activateById(extensionId: string, startup: boolean): TPromise<void> {
let desc = this._registry.getExtensionDescription(extensionId);
if (!desc) {
throw new Error('Extension `' + extensionId + '` is not known');
}
return this._activateExtensions([desc], startup, 0);
}
/**
* Handle semantics related to dependencies for `currentExtension`.
* semantics: `redExtensions` must wait for `greenExtensions`.
*/
private _handleActivateRequest(currentExtension: IExtensionDescription, greenExtensions: { [id: string]: IExtensionDescription; }, redExtensions: IExtensionDescription[]): void {
let depIds = (typeof currentExtension.extensionDependencies === 'undefined' ? [] : currentExtension.extensionDependencies);
let currentExtensionGetsGreenLight = true;
for (let j = 0, lenJ = depIds.length; j < lenJ; j++) {
let depId = depIds[j];
let depDesc = this._registry.getExtensionDescription(depId);
if (!depDesc) {
// Error condition 1: unknown dependency
this._host.showMessage(Severity.Error, nls.localize('unknownDep', "Extension `{1}` failed to activate. Reason: unknown dependency `{0}`.", depId, currentExtension.id));
this._activatedExtensions[currentExtension.id] = new FailedExtension(ExtensionActivationTimes.NONE);
return;
}
if (hasOwnProperty.call(this._activatedExtensions, depId)) {
let dep = this._activatedExtensions[depId];
if (dep.activationFailed) {
// Error condition 2: a dependency has already failed activation
this._host.showMessage(Severity.Error, nls.localize('failedDep1', "Extension `{1}` failed to activate. Reason: dependency `{0}` failed to activate.", depId, currentExtension.id));
this._activatedExtensions[currentExtension.id] = new FailedExtension(ExtensionActivationTimes.NONE);
return;
}
} else {
// must first wait for the dependency to activate
currentExtensionGetsGreenLight = false;
greenExtensions[depId] = depDesc;
}
}
if (currentExtensionGetsGreenLight) {
greenExtensions[currentExtension.id] = currentExtension;
} else {
redExtensions.push(currentExtension);
}
}
private _activateExtensions(extensionDescriptions: IExtensionDescription[], startup: boolean, recursionLevel: number): TPromise<void> {
// console.log(recursionLevel, '_activateExtensions: ', extensionDescriptions.map(p => p.id));
if (extensionDescriptions.length === 0) {
return TPromise.as(void 0);
}
extensionDescriptions = extensionDescriptions.filter((p) => !hasOwnProperty.call(this._activatedExtensions, p.id));
if (extensionDescriptions.length === 0) {
return TPromise.as(void 0);
}
if (recursionLevel > 10) {
// More than 10 dependencies deep => most likely a dependency loop
for (let i = 0, len = extensionDescriptions.length; i < len; i++) {
// Error condition 3: dependency loop
this._host.showMessage(Severity.Error, nls.localize('failedDep2', "Extension `{0}` failed to activate. Reason: more than 10 levels of dependencies (most likely a dependency loop).", extensionDescriptions[i].id));
this._activatedExtensions[extensionDescriptions[i].id] = new FailedExtension(ExtensionActivationTimes.NONE);
}
return TPromise.as(void 0);
}
let greenMap: { [id: string]: IExtensionDescription; } = Object.create(null),
red: IExtensionDescription[] = [];
for (let i = 0, len = extensionDescriptions.length; i < len; i++) {
this._handleActivateRequest(extensionDescriptions[i], greenMap, red);
}
// Make sure no red is also green
for (let i = 0, len = red.length; i < len; i++) {
if (greenMap[red[i].id]) {
delete greenMap[red[i].id];
}
}
let green = Object.keys(greenMap).map(id => greenMap[id]);
// console.log('greenExtensions: ', green.map(p => p.id));
// console.log('redExtensions: ', red.map(p => p.id));
if (red.length === 0) {
// Finally reached only leafs!
return TPromise.join(green.map((p) => this._activateExtension(p, startup))).then(_ => void 0);
}
return this._activateExtensions(green, startup, recursionLevel + 1).then(_ => {
return this._activateExtensions(red, startup, recursionLevel + 1);
});
}
private _activateExtension(extensionDescription: IExtensionDescription, startup: boolean): TPromise<void> {
if (hasOwnProperty.call(this._activatedExtensions, extensionDescription.id)) {
return TPromise.as(void 0);
}
if (hasOwnProperty.call(this._activatingExtensions, extensionDescription.id)) {
return this._activatingExtensions[extensionDescription.id];
}
this._activatingExtensions[extensionDescription.id] = this._host.actualActivateExtension(extensionDescription, startup).then(null, (err) => {
this._host.showMessage(Severity.Error, nls.localize('activationError', "Activating extension `{0}` failed: {1}.", extensionDescription.id, err.message));
console.error('Activating extension `' + extensionDescription.id + '` failed: ', err.message);
console.log('Here is the error stack: ', err.stack);
// Treat the extension as being empty
return new FailedExtension(ExtensionActivationTimes.NONE);
}).then((x: ActivatedExtension) => {
this._activatedExtensions[extensionDescription.id] = x;
delete this._activatingExtensions[extensionDescription.id];
});
return this._activatingExtensions[extensionDescription.id];
}
}

View File

@@ -4,60 +4,21 @@
*--------------------------------------------------------------------------------------------*/
'use strict';
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
import { dispose } from 'vs/base/common/lifecycle';
import { join } from 'path';
import { mkdirp, dirExists } from 'vs/base/node/pfs';
import Severity from 'vs/base/common/severity';
import { TPromise } from 'vs/base/common/winjs.base';
import { AbstractExtensionService, ActivatedExtension } from 'vs/platform/extensions/common/abstractExtensionService';
import { ExtensionDescriptionRegistry } from 'vs/workbench/services/extensions/node/extensionDescriptionRegistry';
import { IExtensionDescription } from 'vs/platform/extensions/common/extensions';
import { ExtHostStorage } from 'vs/workbench/api/node/extHostStorage';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { createApiFactory, initializeExtensionApi } from 'vs/workbench/api/node/extHost.api.impl';
import { IThreadService } from 'vs/workbench/services/thread/common/threadService';
import { MainContext, MainProcessExtensionServiceShape, IWorkspaceData, IEnvironment, IInitData } from './extHost.protocol';
const hasOwnProperty = Object.hasOwnProperty;
/**
* Represents the source code (module) of an extension.
*/
export interface IExtensionModule {
activate(ctx: IExtensionContext): TPromise<IExtensionAPI>;
deactivate(): void;
}
/**
* Represents the API of an extension (return value of `activate`).
*/
export interface IExtensionAPI {
// _extensionAPIBrand: any;
}
export class ExtHostExtension extends ActivatedExtension {
module: IExtensionModule;
exports: IExtensionAPI;
subscriptions: IDisposable[];
constructor(activationFailed: boolean, module: IExtensionModule, exports: IExtensionAPI, subscriptions: IDisposable[]) {
super(activationFailed);
this.module = module;
this.exports = exports;
this.subscriptions = subscriptions;
}
}
export class ExtHostEmptyExtension extends ExtHostExtension {
constructor() {
super(false, { activate: undefined, deactivate: undefined }, undefined, []);
}
}
export interface IExtensionMemento {
get<T>(key: string, defaultValue: T): T;
update(key: string, value: any): Thenable<boolean>;
}
import { MainContext, MainThreadExtensionServiceShape, IWorkspaceData, IEnvironment, IInitData, ExtHostExtensionServiceShape, MainThreadTelemetryShape } from './extHost.protocol';
import { IExtensionMemento, ExtensionsActivator, ActivatedExtension, IExtensionAPI, IExtensionContext, EmptyExtension, IExtensionModule, ExtensionActivationTimesBuilder, ExtensionActivationTimes } from 'vs/workbench/api/node/extHostExtensionActivator';
import { Barrier } from 'vs/workbench/services/extensions/node/barrier';
import { ExtHostThreadService } from 'vs/workbench/services/thread/node/extHostThreadService';
import { realpath } from 'fs';
import { TrieMap } from 'vs/base/common/map';
class ExtensionMemento implements IExtensionMemento {
@@ -145,38 +106,85 @@ class ExtensionStoragePath {
}
}
export interface IExtensionContext {
subscriptions: IDisposable[];
workspaceState: IExtensionMemento;
globalState: IExtensionMemento;
extensionPath: string;
storagePath: string;
asAbsolutePath(relativePath: string): string;
}
export class ExtHostExtensionService extends AbstractExtensionService<ExtHostExtension> {
private _threadService: IThreadService;
private _storage: ExtHostStorage;
private _storagePath: ExtensionStoragePath;
private _proxy: MainProcessExtensionServiceShape;
private _telemetryService: ITelemetryService;
export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
private readonly _barrier: Barrier;
private readonly _registry: ExtensionDescriptionRegistry;
private readonly _threadService: ExtHostThreadService;
private readonly _mainThreadTelemetry: MainThreadTelemetryShape;
private readonly _storage: ExtHostStorage;
private readonly _storagePath: ExtensionStoragePath;
private readonly _proxy: MainThreadExtensionServiceShape;
private _activator: ExtensionsActivator;
private _extensionPathIndex: TPromise<TrieMap<IExtensionDescription>>;
/**
* This class is constructed manually because it is a service, so it doesn't use any ctor injection
*/
constructor(initData: IInitData, threadService: IThreadService, telemetryService: ITelemetryService) {
super(false);
this._registry.registerExtensions(initData.extensions);
constructor(initData: IInitData, threadService: ExtHostThreadService) {
this._barrier = new Barrier();
this._registry = new ExtensionDescriptionRegistry(initData.extensions);
this._threadService = threadService;
this._mainThreadTelemetry = threadService.get(MainContext.MainThreadTelemetry);
this._storage = new ExtHostStorage(threadService);
this._storagePath = new ExtensionStoragePath(initData.workspace, initData.environment);
this._proxy = this._threadService.get(MainContext.MainProcessExtensionService);
this._telemetryService = telemetryService;
this._proxy = this._threadService.get(MainContext.MainThreadExtensionService);
this._activator = null;
// initialize API first
const apiFactory = createApiFactory(initData, threadService, this, this._telemetryService);
initializeExtensionApi(this, apiFactory).then(() => this._triggerOnReady());
// initialize API first (i.e. do not release barrier until the API is initialized)
const apiFactory = createApiFactory(initData, threadService, this);
initializeExtensionApi(this, apiFactory).then(() => {
this._activator = new ExtensionsActivator(this._registry, {
showMessage: (severity: Severity, message: string): void => {
this._proxy.$localShowMessage(severity, message);
switch (severity) {
case Severity.Error:
console.error(message);
break;
case Severity.Warning:
console.warn(message);
break;
default:
console.log(message);
}
},
actualActivateExtension: (extensionDescription: IExtensionDescription, startup: boolean): TPromise<ActivatedExtension> => {
return this._activateExtension(extensionDescription, startup);
}
});
this._barrier.open();
});
}
public onExtensionAPIReady(): TPromise<boolean> {
return this._barrier.wait();
}
public isActivated(extensionId: string): boolean {
if (this._barrier.isOpen()) {
return this._activator.isActivated(extensionId);
}
return false;
}
public activateByEvent(activationEvent: string, startup: boolean): TPromise<void> {
if (this._barrier.isOpen()) {
return this._activator.activateByEvent(activationEvent, startup);
} else {
return this._barrier.wait().then(() => this._activator.activateByEvent(activationEvent, startup));
}
}
public activateById(extensionId: string, startup: boolean): TPromise<void> {
if (this._barrier.isOpen()) {
return this._activator.activateById(extensionId, startup);
} else {
return this._barrier.wait().then(() => this._activator.activateById(extensionId, startup));
}
}
public getAllExtensionDescriptions(): IExtensionDescription[] {
@@ -187,30 +195,51 @@ export class ExtHostExtensionService extends AbstractExtensionService<ExtHostExt
return this._registry.getExtensionDescription(extensionId);
}
public $localShowMessage(severity: Severity, msg: string): void {
switch (severity) {
case Severity.Error:
console.error(msg);
break;
case Severity.Warning:
console.warn(msg);
break;
default:
console.log(msg);
public getExtensionExports(extensionId: string): IExtensionAPI {
if (this._barrier.isOpen()) {
return this._activator.getActivatedExtension(extensionId).exports;
} else {
return null;
}
}
public get(extensionId: string): IExtensionAPI {
if (!hasOwnProperty.call(this._activatedExtensions, extensionId)) {
throw new Error('Extension `' + extensionId + '` is not known or not activated');
// create trie to enable fast 'filename -> extension id' look up
public getExtensionPathIndex(): TPromise<TrieMap<IExtensionDescription>> {
if (!this._extensionPathIndex) {
const trie = new TrieMap<IExtensionDescription>();
const extensions = this.getAllExtensionDescriptions().map(ext => {
if (!ext.main) {
return undefined;
}
return new TPromise((resolve, reject) => {
realpath(ext.extensionFolderPath, (err, path) => {
if (err) {
reject(err);
} else {
trie.insert(path, ext);
resolve(void 0);
}
});
});
});
this._extensionPathIndex = TPromise.join(extensions).then(() => trie);
}
return this._activatedExtensions[extensionId].exports;
return this._extensionPathIndex;
}
public deactivate(extensionId: string): TPromise<void> {
let result: TPromise<void> = TPromise.as(void 0);
let extension = this._activatedExtensions[extensionId];
if (!this._barrier.isOpen()) {
return result;
}
if (!this._activator.isActivated(extensionId)) {
return result;
}
let extension = this._activator.getActivatedExtension(extensionId);
if (!extension) {
return result;
}
@@ -237,15 +266,43 @@ export class ExtHostExtensionService extends AbstractExtensionService<ExtHostExt
return result;
}
// -- overwriting AbstractExtensionService
// --- impl
protected _showMessage(severity: Severity, msg: string): void {
this._proxy.$localShowMessage(severity, msg);
this.$localShowMessage(severity, msg);
private _activateExtension(extensionDescription: IExtensionDescription, startup: boolean): TPromise<ActivatedExtension> {
return this._doActivateExtension(extensionDescription, startup).then((activatedExtension) => {
const activationTimes = activatedExtension.activationTimes;
this._proxy.$onExtensionActivated(extensionDescription.id, activationTimes.startup, activationTimes.codeLoadingTime, activationTimes.activateCallTime, activationTimes.activateResolvedTime);
return activatedExtension;
}, (err) => {
this._proxy.$onExtensionActivationFailed(extensionDescription.id);
throw err;
});
}
protected _createFailedExtension() {
return new ExtHostExtension(true, { activate: undefined, deactivate: undefined }, undefined, []);
private _doActivateExtension(extensionDescription: IExtensionDescription, startup: boolean): TPromise<ActivatedExtension> {
let event = getTelemetryActivationEvent(extensionDescription);
this._mainThreadTelemetry.$publicLog('activatePlugin', event);
if (!extensionDescription.main) {
// Treat the extension as being empty => NOT AN ERROR CASE
return TPromise.as(new EmptyExtension(ExtensionActivationTimes.NONE));
}
const activationTimesBuilder = new ExtensionActivationTimesBuilder(startup);
return TPromise.join<any>([
loadCommonJSModule(extensionDescription.main, activationTimesBuilder),
this._loadExtensionContext(extensionDescription)
]).then(values => {
return ExtHostExtensionService._callActivate(<IExtensionModule>values[0], <IExtensionContext>values[1], activationTimesBuilder);
}, (errors: any[]) => {
// Avoid failing with an array of errors, fail with a single error
if (errors[0]) {
return TPromise.wrapError<ActivatedExtension>(errors[0]);
}
if (errors[1]) {
return TPromise.wrapError<ActivatedExtension>(errors[1]);
}
return undefined;
});
}
private _loadExtensionContext(extensionDescription: IExtensionDescription): TPromise<IExtensionContext> {
@@ -269,58 +326,30 @@ export class ExtHostExtensionService extends AbstractExtensionService<ExtHostExt
});
}
protected _actualActivateExtension(extensionDescription: IExtensionDescription): TPromise<ExtHostExtension> {
return this._doActualActivateExtension(extensionDescription).then((activatedExtension) => {
this._proxy.$onExtensionActivated(extensionDescription.id);
return activatedExtension;
}, (err) => {
this._proxy.$onExtensionActivationFailed(extensionDescription.id);
throw err;
});
}
private _doActualActivateExtension(extensionDescription: IExtensionDescription): TPromise<ExtHostExtension> {
let event = getTelemetryActivationEvent(extensionDescription);
this._telemetryService.publicLog('activatePlugin', event);
if (!extensionDescription.main) {
// Treat the extension as being empty => NOT AN ERROR CASE
return TPromise.as(new ExtHostEmptyExtension());
}
return this.onReady().then(() => {
return TPromise.join<any>([
loadCommonJSModule(extensionDescription.main),
this._loadExtensionContext(extensionDescription)
]).then(values => {
return ExtHostExtensionService._callActivate(<IExtensionModule>values[0], <IExtensionContext>values[1]);
}, (errors: any[]) => {
// Avoid failing with an array of errors, fail with a single error
if (errors[0]) {
return TPromise.wrapError<ExtHostExtension>(errors[0]);
}
if (errors[1]) {
return TPromise.wrapError<ExtHostExtension>(errors[1]);
}
return undefined;
});
});
}
private static _callActivate(extensionModule: IExtensionModule, context: IExtensionContext): TPromise<ExtHostExtension> {
private static _callActivate(extensionModule: IExtensionModule, context: IExtensionContext, activationTimesBuilder: ExtensionActivationTimesBuilder): TPromise<ActivatedExtension> {
// Make sure the extension's surface is not undefined
extensionModule = extensionModule || {
activate: undefined,
deactivate: undefined
};
return this._callActivateOptional(extensionModule, context).then((extensionExports) => {
return new ExtHostExtension(false, extensionModule, extensionExports, context.subscriptions);
return this._callActivateOptional(extensionModule, context, activationTimesBuilder).then((extensionExports) => {
return new ActivatedExtension(false, activationTimesBuilder.build(), extensionModule, extensionExports, context.subscriptions);
});
}
private static _callActivateOptional(extensionModule: IExtensionModule, context: IExtensionContext): TPromise<IExtensionAPI> {
private static _callActivateOptional(extensionModule: IExtensionModule, context: IExtensionContext, activationTimesBuilder: ExtensionActivationTimesBuilder): TPromise<IExtensionAPI> {
if (typeof extensionModule.activate === 'function') {
try {
return TPromise.as(extensionModule.activate.apply(global, [context]));
activationTimesBuilder.activateCallStart();
const activateResult = extensionModule.activate.apply(global, [context]);
activationTimesBuilder.activateCallStop();
activationTimesBuilder.activateResolveStart();
return TPromise.as(activateResult).then((value) => {
activationTimesBuilder.activateResolveStop();
return value;
});
} catch (err) {
return TPromise.wrapError(err);
}
@@ -332,18 +361,20 @@ export class ExtHostExtensionService extends AbstractExtensionService<ExtHostExt
// -- called by main thread
public $activateExtension(extensionDescription: IExtensionDescription): TPromise<void> {
return this._activateExtension(extensionDescription);
public $activateByEvent(activationEvent: string): TPromise<void> {
return this.activateByEvent(activationEvent, false);
}
}
function loadCommonJSModule<T>(modulePath: string): TPromise<T> {
function loadCommonJSModule<T>(modulePath: string, activationTimesBuilder: ExtensionActivationTimesBuilder): TPromise<T> {
let r: T = null;
activationTimesBuilder.codeLoadingStart();
try {
r = require.__$__nodeRequire<T>(modulePath);
} catch (e) {
return TPromise.wrapError<T>(e);
} finally {
activationTimesBuilder.codeLoadingStop();
}
return TPromise.as(r);
}

View File

@@ -87,12 +87,11 @@ class FileSystemWatcher implements _FileSystemWatcher {
}
}
export class ExtHostFileSystemEventService extends ExtHostFileSystemEventServiceShape {
export class ExtHostFileSystemEventService implements ExtHostFileSystemEventServiceShape {
private _emitter = new Emitter<FileSystemEvents>();
constructor() {
super();
}
public createFileSystemWatcher(globPattern: string, ignoreCreateEvents?: boolean, ignoreChangeEvents?: boolean, ignoreDeleteEvents?: boolean): _FileSystemWatcher {

View File

@@ -6,7 +6,7 @@
import { ExtHostHeapServiceShape } from './extHost.protocol';
export class ExtHostHeapService extends ExtHostHeapServiceShape {
export class ExtHostHeapService implements ExtHostHeapServiceShape {
private static _idPool = 0;

View File

@@ -7,7 +7,6 @@
import URI from 'vs/base/common/uri';
import { TPromise } from 'vs/base/common/winjs.base';
import { mixin } from 'vs/base/common/objects';
import { IThreadService } from 'vs/workbench/services/thread/common/threadService';
import * as vscode from 'vscode';
import * as TypeConverters from 'vs/workbench/api/node/extHostTypeConverters';
import { Range, Disposable, CompletionList, CompletionItem, SnippetString } from 'vs/workbench/api/node/extHostTypes';
@@ -19,10 +18,13 @@ import { ExtHostCommands, CommandsConverter } from 'vs/workbench/api/node/extHos
import { ExtHostDiagnostics } from 'vs/workbench/api/node/extHostDiagnostics';
import { IWorkspaceSymbolProvider } from 'vs/workbench/parts/search/common/search';
import { asWinJsPromise } from 'vs/base/common/async';
import { MainContext, MainThreadLanguageFeaturesShape, ExtHostLanguageFeaturesShape, ObjectIdentifier } from './extHost.protocol';
import { MainContext, MainThreadTelemetryShape, MainThreadLanguageFeaturesShape, ExtHostLanguageFeaturesShape, ObjectIdentifier, IRawColorInfo, IRawColorFormatMap, IMainContext } from './extHost.protocol';
import { regExpLeadsToEndlessLoop } from 'vs/base/common/strings';
import { IPosition } from 'vs/editor/common/core/position';
import { IRange } from 'vs/editor/common/core/range';
import { containsCommandLink } from 'vs/base/common/htmlContent';
import { isFalsyOrEmpty } from 'vs/base/common/arrays';
import { once } from 'vs/base/common/functional';
// --- adapter
@@ -174,12 +176,12 @@ class TypeDefinitionAdapter {
class HoverAdapter {
private _documents: ExtHostDocuments;
private _provider: vscode.HoverProvider;
constructor(documents: ExtHostDocuments, provider: vscode.HoverProvider) {
this._documents = documents;
this._provider = provider;
constructor(
private readonly _documents: ExtHostDocuments,
private readonly _provider: vscode.HoverProvider,
private readonly _telemetryLog: (name: string, data: object) => void,
) {
//
}
public provideHover(resource: URI, position: IPosition): TPromise<modes.Hover> {
@@ -188,7 +190,7 @@ class HoverAdapter {
let pos = TypeConverters.toPosition(position);
return asWinJsPromise(token => this._provider.provideHover(doc, pos, token)).then(value => {
if (!value) {
if (!value || isFalsyOrEmpty(value.contents)) {
return undefined;
}
if (!value.range) {
@@ -198,7 +200,14 @@ class HoverAdapter {
value.range = new Range(pos, pos);
}
return TypeConverters.fromHover(value);
const result = TypeConverters.fromHover(value);
// we wanna know which extension uses command links
// because that is a potential trick-attack on users
if (result.contents.some(h => containsCommandLink(h.value))) {
this._telemetryLog('usesCommandLink', { from: 'hover' });
}
return result;
});
}
}
@@ -635,10 +644,12 @@ class SignatureHelpAdapter {
class LinkProviderAdapter {
private _documents: ExtHostDocuments;
private _heapService: ExtHostHeapService;
private _provider: vscode.DocumentLinkProvider;
constructor(documents: ExtHostDocuments, provider: vscode.DocumentLinkProvider) {
constructor(documents: ExtHostDocuments, heapService: ExtHostHeapService, provider: vscode.DocumentLinkProvider) {
this._documents = documents;
this._heapService = heapService;
this._provider = provider;
}
@@ -646,51 +657,120 @@ class LinkProviderAdapter {
const doc = this._documents.getDocumentData(resource).document;
return asWinJsPromise(token => this._provider.provideDocumentLinks(doc, token)).then(links => {
if (Array.isArray(links)) {
return links.map(TypeConverters.DocumentLink.from);
if (!Array.isArray(links)) {
return undefined;
}
return undefined;
const result: modes.ILink[] = [];
for (const link of links) {
let data = TypeConverters.DocumentLink.from(link);
let id = this._heapService.keep(link);
ObjectIdentifier.mixin(data, id);
result.push(data);
}
return result;
});
}
resolveLink(link: modes.ILink): TPromise<modes.ILink> {
if (typeof this._provider.resolveDocumentLink === 'function') {
return asWinJsPromise(token => this._provider.resolveDocumentLink(TypeConverters.DocumentLink.to(link), token)).then(value => {
if (value) {
return TypeConverters.DocumentLink.from(value);
}
return undefined;
});
if (typeof this._provider.resolveDocumentLink !== 'function') {
return undefined;
}
return undefined;
const id = ObjectIdentifier.of(link);
const item = this._heapService.get<vscode.DocumentLink>(id);
if (!item) {
return undefined;
}
return asWinJsPromise(token => this._provider.resolveDocumentLink(item, token)).then(value => {
if (value) {
return TypeConverters.DocumentLink.from(value);
}
return undefined;
});
}
}
class ColorProviderAdapter {
private static _colorFormatHandlePool: number = 0;
constructor(
private _proxy: MainThreadLanguageFeaturesShape,
private _documents: ExtHostDocuments,
private _colorFormatCache: Map<string, number>,
private _provider: vscode.DocumentColorProvider
) { }
provideColors(resource: URI): TPromise<IRawColorInfo[]> {
const doc = this._documents.getDocumentData(resource).document;
return asWinJsPromise(token => this._provider.provideDocumentColors(doc, token)).then(colors => {
if (!Array.isArray(colors)) {
return [];
}
const newRawColorFormats: IRawColorFormatMap = [];
const getFormatId = (format: string) => {
let id = this._colorFormatCache.get(format);
if (typeof id !== 'number') {
id = ColorProviderAdapter._colorFormatHandlePool++;
this._colorFormatCache.set(format, id);
newRawColorFormats.push([id, format]);
}
return id;
};
const colorInfos: IRawColorInfo[] = colors.map(ci => {
const availableFormats = ci.availableFormats.map(format => {
if (typeof format === 'string') {
return getFormatId(format);
} else {
return [getFormatId(format.opaque), getFormatId(format.transparent)] as [number, number];
}
});
return {
color: [ci.color.red, ci.color.green, ci.color.blue, ci.color.alpha] as [number, number, number, number],
availableFormats: availableFormats,
range: TypeConverters.fromRange(ci.range)
};
});
this._proxy.$registerColorFormats(newRawColorFormats);
return colorInfos;
});
}
}
type Adapter = OutlineAdapter | CodeLensAdapter | DefinitionAdapter | HoverAdapter
| DocumentHighlightAdapter | ReferenceAdapter | QuickFixAdapter | DocumentFormattingAdapter
| RangeFormattingAdapter | OnTypeFormattingAdapter | NavigateTypeAdapter | RenameAdapter
| SuggestAdapter | SignatureHelpAdapter | LinkProviderAdapter | ImplementationAdapter | TypeDefinitionAdapter;
| SuggestAdapter | SignatureHelpAdapter | LinkProviderAdapter | ImplementationAdapter | TypeDefinitionAdapter | ColorProviderAdapter;
export class ExtHostLanguageFeatures extends ExtHostLanguageFeaturesShape {
export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
private static _handlePool: number = 0;
private _proxy: MainThreadLanguageFeaturesShape;
private _telemetry: MainThreadTelemetryShape;
private _documents: ExtHostDocuments;
private _commands: ExtHostCommands;
private _heapService: ExtHostHeapService;
private _diagnostics: ExtHostDiagnostics;
private _adapter = new Map<number, Adapter>();
private _colorFormatCache = new Map<string, number>();
constructor(
threadService: IThreadService,
mainContext: IMainContext,
documents: ExtHostDocuments,
commands: ExtHostCommands,
heapMonitor: ExtHostHeapService,
diagnostics: ExtHostDiagnostics
) {
super();
this._proxy = threadService.get(MainContext.MainThreadLanguageFeatures);
this._proxy = mainContext.get(MainContext.MainThreadLanguageFeatures);
this._telemetry = mainContext.get(MainContext.MainThreadTelemetry);
this._documents = documents;
this._commands = commands;
this._heapService = heapMonitor;
@@ -792,9 +872,12 @@ export class ExtHostLanguageFeatures extends ExtHostLanguageFeaturesShape {
// --- extra info
registerHoverProvider(selector: vscode.DocumentSelector, provider: vscode.HoverProvider): vscode.Disposable {
registerHoverProvider(selector: vscode.DocumentSelector, provider: vscode.HoverProvider, extensionId?: string): vscode.Disposable {
const handle = this._nextHandle();
this._adapter.set(handle, new HoverAdapter(this._documents, provider));
this._adapter.set(handle, new HoverAdapter(this._documents, provider, once((name, data) => {
data['extension'] = extensionId;
this._telemetry.$publicLog(name, data);
})));
this._proxy.$registerHoverProvider(handle, selector);
return this._createDisposable(handle);
}
@@ -941,7 +1024,7 @@ export class ExtHostLanguageFeatures extends ExtHostLanguageFeaturesShape {
registerDocumentLinkProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentLinkProvider): vscode.Disposable {
const handle = this._nextHandle();
this._adapter.set(handle, new LinkProviderAdapter(this._documents, provider));
this._adapter.set(handle, new LinkProviderAdapter(this._documents, this._heapService, provider));
this._proxy.$registerDocumentLinkProvider(handle, selector);
return this._createDisposable(handle);
}
@@ -954,6 +1037,17 @@ export class ExtHostLanguageFeatures extends ExtHostLanguageFeaturesShape {
return this._withAdapter(handle, LinkProviderAdapter, adapter => adapter.resolveLink(link));
}
registerColorProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentColorProvider): vscode.Disposable {
const handle = this._nextHandle();
this._adapter.set(handle, new ColorProviderAdapter(this._proxy, this._documents, this._colorFormatCache, provider));
this._proxy.$registerDocumentColorProvider(handle, selector);
return this._createDisposable(handle);
}
$provideDocumentColors(handle: number, resource: URI): TPromise<IRawColorInfo[]> {
return this._withAdapter(handle, ColorProviderAdapter, adapter => adapter.provideColors(resource));
}
// --- configuration
setLanguageConfiguration(languageId: string, configuration: vscode.LanguageConfiguration): vscode.Disposable {

View File

@@ -5,17 +5,16 @@
'use strict';
import { TPromise } from 'vs/base/common/winjs.base';
import { IThreadService } from 'vs/workbench/services/thread/common/threadService';
import { MainContext, MainThreadLanguagesShape } from './extHost.protocol';
import { MainContext, MainThreadLanguagesShape, IMainContext } from './extHost.protocol';
export class ExtHostLanguages {
private _proxy: MainThreadLanguagesShape;
constructor(
threadService: IThreadService
mainContext: IMainContext
) {
this._proxy = threadService.get(MainContext.MainThreadLanguages);
this._proxy = mainContext.get(MainContext.MainThreadLanguages);
}
getLanguages(): TPromise<string[]> {

View File

@@ -4,37 +4,38 @@
*--------------------------------------------------------------------------------------------*/
'use strict';
import { IThreadService } from 'vs/workbench/services/thread/common/threadService';
import Severity from 'vs/base/common/severity';
import vscode = require('vscode');
import { MainContext, MainThreadMessageServiceShape } from './extHost.protocol';
import { MainContext, MainThreadMessageServiceShape, MainThreadMessageOptions, IMainContext } from './extHost.protocol';
import { IExtensionDescription } from 'vs/platform/extensions/common/extensions';
const emptyMessageOptions: vscode.MessageOptions = Object.create(null);
function isMessageItem<T>(item: any): item is vscode.MessageItem {
return item && item.title;
}
function parseMessageArguments(first: vscode.MessageOptions | string | vscode.MessageItem, rest: (string | vscode.MessageItem)[]): { options: vscode.MessageOptions; items: (string | vscode.MessageItem)[]; } {
if (typeof first === 'string' || isMessageItem(first)) {
return { options: emptyMessageOptions, items: [first, ...rest] };
} else {
return { options: first || emptyMessageOptions, items: rest };
}
}
export class ExtHostMessageService {
private _proxy: MainThreadMessageServiceShape;
constructor(threadService: IThreadService) {
this._proxy = threadService.get(MainContext.MainThreadMessageService);
constructor(mainContext: IMainContext) {
this._proxy = mainContext.get(MainContext.MainThreadMessageService);
}
showMessage(severity: Severity, message: string, optionsOrFirstItem: vscode.MessageOptions | string, rest: string[]): Thenable<string | undefined>;
showMessage(severity: Severity, message: string, optionsOrFirstItem: vscode.MessageOptions | vscode.MessageItem, rest: vscode.MessageItem[]): Thenable<vscode.MessageItem | undefined>;
showMessage(severity: Severity, message: string, optionsOrFirstItem: vscode.MessageOptions | string | vscode.MessageItem, rest: (string | vscode.MessageItem)[]): Thenable<string | vscode.MessageItem | undefined> {
const { options, items } = parseMessageArguments(optionsOrFirstItem, rest);
showMessage(extension: IExtensionDescription, severity: Severity, message: string, optionsOrFirstItem: vscode.MessageOptions | string, rest: string[]): Thenable<string | undefined>;
showMessage(extension: IExtensionDescription, severity: Severity, message: string, optionsOrFirstItem: vscode.MessageOptions | vscode.MessageItem, rest: vscode.MessageItem[]): Thenable<vscode.MessageItem | undefined>;
showMessage(extension: IExtensionDescription, severity: Severity, message: string, optionsOrFirstItem: vscode.MessageOptions | string | vscode.MessageItem, rest: (string | vscode.MessageItem)[]): Thenable<string | vscode.MessageItem | undefined> {
let options: MainThreadMessageOptions = { extension };
let items: (string | vscode.MessageItem)[];
if (typeof optionsOrFirstItem === 'string' || isMessageItem(optionsOrFirstItem)) {
items = [optionsOrFirstItem, ...rest];
} else {
options.modal = optionsOrFirstItem && optionsOrFirstItem.modal;
items = rest;
}
const commands: { title: string; isCloseAffordance: boolean; handle: number; }[] = [];
for (let handle = 0; handle < items.length; handle++) {

View File

@@ -4,8 +4,7 @@
*--------------------------------------------------------------------------------------------*/
'use strict';
import { IThreadService } from 'vs/workbench/services/thread/common/threadService';
import { MainContext, MainThreadOutputServiceShape } from './extHost.protocol';
import { MainContext, MainThreadOutputServiceShape, IMainContext } from './extHost.protocol';
import * as vscode from 'vscode';
export class ExtHostOutputChannel implements vscode.OutputChannel {
@@ -64,8 +63,8 @@ export class ExtHostOutputService {
private _proxy: MainThreadOutputServiceShape;
constructor(threadService: IThreadService) {
this._proxy = threadService.get(MainContext.MainThreadOutputService);
constructor(mainContext: IMainContext) {
this._proxy = mainContext.get(MainContext.MainThreadOutputService);
}
createOutputChannel(name: string): vscode.OutputChannel {

View File

@@ -7,21 +7,19 @@
import { TPromise } from 'vs/base/common/winjs.base';
import { wireCancellationToken } from 'vs/base/common/async';
import { CancellationToken } from 'vs/base/common/cancellation';
import { IThreadService } from 'vs/workbench/services/thread/common/threadService';
import { QuickPickOptions, QuickPickItem, InputBoxOptions } from 'vscode';
import { MainContext, MainThreadQuickOpenShape, ExtHostQuickOpenShape, MyQuickPickItems } from './extHost.protocol';
import { MainContext, MainThreadQuickOpenShape, ExtHostQuickOpenShape, MyQuickPickItems, IMainContext } from './extHost.protocol';
export type Item = string | QuickPickItem;
export class ExtHostQuickOpen extends ExtHostQuickOpenShape {
export class ExtHostQuickOpen implements ExtHostQuickOpenShape {
private _proxy: MainThreadQuickOpenShape;
private _onDidSelectItem: (handle: number) => void;
private _validateInput: (input: string) => string;
constructor(threadService: IThreadService) {
super();
this._proxy = threadService.get(MainContext.MainThreadQuickOpen);
constructor(mainContext: IMainContext) {
this._proxy = mainContext.get(MainContext.MainThreadQuickOpen);
}
showQuickPick(itemsOrItemsPromise: string[] | Thenable<string[]>, options?: QuickPickOptions, token?: CancellationToken): Thenable<string | undefined>;

View File

@@ -8,9 +8,9 @@ import URI from 'vs/base/common/uri';
import { TPromise } from 'vs/base/common/winjs.base';
import Event, { Emitter } from 'vs/base/common/event';
import { asWinJsPromise } from 'vs/base/common/async';
import { IThreadService } from 'vs/workbench/services/thread/common/threadService';
import { IExtensionDescription } from 'vs/platform/extensions/common/extensions';
import { ExtHostCommands, CommandsConverter } from 'vs/workbench/api/node/extHostCommands';
import { MainContext, MainThreadSCMShape, SCMRawResource } from './extHost.protocol';
import { MainContext, MainThreadSCMShape, SCMRawResource, IMainContext } from './extHost.protocol';
import * as vscode from 'vscode';
function getIconPath(decorations: vscode.SourceControlResourceThemableDecorations) {
@@ -33,7 +33,7 @@ export class ExtHostSCMInputBox {
}
set value(value: string) {
this._proxy.$setInputBoxValue(value);
this._proxy.$setInputBoxValue(this._sourceControlHandle, value);
this.updateValue(value);
}
@@ -43,13 +43,7 @@ export class ExtHostSCMInputBox {
return this._onDidChange.event;
}
private _onDidAccept = new Emitter<string>();
get onDidAccept(): Event<string> {
return this._onDidAccept.event;
}
constructor(private _proxy: MainThreadSCMShape) {
constructor(private _proxy: MainThreadSCMShape, private _sourceControlHandle: number) {
// noop
}
@@ -57,10 +51,6 @@ export class ExtHostSCMInputBox {
this.updateValue(value);
}
$onInputBoxAcceptChanges(): void {
this._onDidAccept.fire(this._value);
}
private updateValue(value: string): void {
this._value = value;
this._onDidChange.fire(value);
@@ -71,7 +61,8 @@ class ExtHostSourceControlResourceGroup implements vscode.SourceControlResourceG
private static _handlePool: number = 0;
private _resourceHandlePool: number = 0;
private _resourceStates: Map<ResourceStateHandle, vscode.SourceControlResourceState> = new Map<ResourceStateHandle, vscode.SourceControlResourceState>();
private _resourceStates: vscode.SourceControlResourceState[] = [];
private _resourceStatesMap: Map<ResourceStateHandle, vscode.SourceControlResourceState> = new Map<ResourceStateHandle, vscode.SourceControlResourceState>();
get id(): string {
return this._id;
@@ -97,12 +88,17 @@ class ExtHostSourceControlResourceGroup implements vscode.SourceControlResourceG
this._proxy.$updateGroup(this._sourceControlHandle, this._handle, { hideWhenEmpty });
}
get resourceStates(): vscode.SourceControlResourceState[] {
return [...this._resourceStates];
}
set resourceStates(resources: vscode.SourceControlResourceState[]) {
this._resourceStates.clear();
this._resourceStatesMap.clear();
this._resourceStates = [...resources];
const rawResources = resources.map(r => {
const handle = this._resourceHandlePool++;
this._resourceStates.set(handle, r);
this._resourceStatesMap.set(handle, r);
const sourceUri = r.resourceUri.toString();
const command = this._commands.toInternal(r.command);
@@ -119,10 +115,11 @@ class ExtHostSourceControlResourceGroup implements vscode.SourceControlResourceG
icons.push(darkIconPath);
}
const tooltip = (r.decorations && r.decorations.tooltip) || '';
const strikeThrough = r.decorations && !!r.decorations.strikeThrough;
const faded = r.decorations && !!r.decorations.faded;
return [handle, sourceUri, command, icons, strikeThrough, faded] as SCMRawResource;
return [handle, sourceUri, command, icons, tooltip, strikeThrough, faded] as SCMRawResource;
});
this._proxy.$updateGroupResourceStates(this._sourceControlHandle, this._handle, rawResources);
@@ -144,7 +141,7 @@ class ExtHostSourceControlResourceGroup implements vscode.SourceControlResourceG
}
getResourceState(handle: number): vscode.SourceControlResourceState | undefined {
return this._resourceStates.get(handle);
return this._resourceStatesMap.get(handle);
}
dispose(): void {
@@ -165,6 +162,9 @@ class ExtHostSourceControl implements vscode.SourceControl {
return this._label;
}
private _inputBox: ExtHostSCMInputBox;
get inputBox(): ExtHostSCMInputBox { return this._inputBox; }
private _count: number | undefined = undefined;
get count(): number | undefined {
@@ -232,6 +232,7 @@ class ExtHostSourceControl implements vscode.SourceControl {
private _id: string,
private _label: string,
) {
this._inputBox = new ExtHostSCMInputBox(this._proxy, this._handle);
this._proxy.$registerSourceControl(this._handle, _id, _label);
}
@@ -260,22 +261,16 @@ export class ExtHostSCM {
private _proxy: MainThreadSCMShape;
private _sourceControls: Map<ProviderHandle, ExtHostSourceControl> = new Map<ProviderHandle, ExtHostSourceControl>();
private _sourceControlsByExtension: Map<string, ExtHostSourceControl[]> = new Map<string, ExtHostSourceControl[]>();
private _onDidChangeActiveProvider = new Emitter<vscode.SourceControl>();
get onDidChangeActiveProvider(): Event<vscode.SourceControl> { return this._onDidChangeActiveProvider.event; }
private _activeProvider: vscode.SourceControl | undefined;
get activeProvider(): vscode.SourceControl | undefined { return this._activeProvider; }
private _inputBox: ExtHostSCMInputBox;
get inputBox(): ExtHostSCMInputBox { return this._inputBox; }
constructor(
threadService: IThreadService,
mainContext: IMainContext,
private _commands: ExtHostCommands
) {
this._proxy = threadService.get(MainContext.MainThreadSCM);
this._inputBox = new ExtHostSCMInputBox(this._proxy);
this._proxy = mainContext.get(MainContext.MainThreadSCM);
_commands.registerArgumentProcessor({
processArgument: arg => {
@@ -301,6 +296,14 @@ export class ExtHostSCM {
}
return sourceControl.getResourceGroup(arg.groupHandle);
} else if (arg && arg.$mid === 5) {
const sourceControl = this._sourceControls.get(arg.handle);
if (!sourceControl) {
return arg;
}
return sourceControl;
}
return arg;
@@ -308,14 +311,27 @@ export class ExtHostSCM {
});
}
createSourceControl(id: string, label: string): vscode.SourceControl {
createSourceControl(extension: IExtensionDescription, id: string, label: string): vscode.SourceControl {
const handle = ExtHostSCM._handlePool++;
const sourceControl = new ExtHostSourceControl(this._proxy, this._commands.converter, id, label);
this._sourceControls.set(handle, sourceControl);
const sourceControls = this._sourceControlsByExtension.get(extension.id) || [];
sourceControls.push(sourceControl);
this._sourceControlsByExtension.set(extension.id, sourceControls);
return sourceControl;
}
// Deprecated
getLastInputBox(extension: IExtensionDescription): ExtHostSCMInputBox {
const sourceControls = this._sourceControlsByExtension.get(extension.id);
const sourceControl = sourceControls && sourceControls[sourceControls.length - 1];
const inputBox = sourceControl && sourceControl.inputBox;
return inputBox;
}
$provideOriginalResource(sourceControlHandle: number, uri: URI): TPromise<URI> {
const sourceControl = this._sourceControls.get(sourceControlHandle);
@@ -329,18 +345,14 @@ export class ExtHostSCM {
});
}
$onActiveSourceControlChange(handle: number): TPromise<void> {
this._activeProvider = this._sourceControls.get(handle);
return TPromise.as(null);
}
$onInputBoxValueChange(sourceControlHandle: number, value: string): TPromise<void> {
const sourceControl = this._sourceControls.get(sourceControlHandle);
$onInputBoxValueChange(value: string): TPromise<void> {
this._inputBox.$onInputBoxValueChange(value);
return TPromise.as(null);
}
if (!sourceControl || !sourceControl.quickDiffProvider) {
return TPromise.as(null);
}
$onInputBoxAcceptChanges(): TPromise<void> {
this._inputBox.$onInputBoxAcceptChanges();
sourceControl.inputBox.$onInputBoxValueChange(value);
return TPromise.as(null);
}
}

View File

@@ -4,11 +4,10 @@
*--------------------------------------------------------------------------------------------*/
'use strict';
import { IThreadService } from 'vs/workbench/services/thread/common/threadService';
import { StatusbarAlignment as MainThreadStatusBarAlignment } from 'vs/platform/statusbar/common/statusbar';
import { StatusBarAlignment as ExtHostStatusBarAlignment, Disposable, ThemeColor } from './extHostTypes';
import { StatusBarItem, StatusBarAlignment } from 'vscode';
import { MainContext, MainThreadStatusBarShape } from './extHost.protocol';
import { MainContext, MainThreadStatusBarShape, IMainContext } from './extHost.protocol';
export class ExtHostStatusBarEntry implements StatusBarItem {
private static ID_GEN = 0;
@@ -163,8 +162,8 @@ export class ExtHostStatusBar {
private _proxy: MainThreadStatusBarShape;
private _statusMessage: StatusBarMessage;
constructor(threadService: IThreadService) {
this._proxy = threadService.get(MainContext.MainThreadStatusBar);
constructor(mainContext: IMainContext) {
this._proxy = mainContext.get(MainContext.MainThreadStatusBar);
this._statusMessage = new StatusBarMessage(this);
}

View File

@@ -5,15 +5,14 @@
'use strict';
import { TPromise } from 'vs/base/common/winjs.base';
import { IThreadService } from 'vs/workbench/services/thread/common/threadService';
import { MainContext, MainThreadStorageShape } from './extHost.protocol';
import { MainContext, MainThreadStorageShape, IMainContext } from './extHost.protocol';
export class ExtHostStorage {
private _proxy: MainThreadStorageShape;
constructor(threadService: IThreadService) {
this._proxy = threadService.get(MainContext.MainThreadStorage);
constructor(mainContext: IMainContext) {
this._proxy = mainContext.get(MainContext.MainThreadStorage);
}
getValue<T>(shared: boolean, key: string, defaultValue?: T): TPromise<T> {

View File

@@ -12,8 +12,7 @@ import { asWinJsPromise } from 'vs/base/common/async';
import { IExtensionDescription } from 'vs/platform/extensions/common/extensions';
import * as TaskSystem from 'vs/workbench/parts/tasks/common/tasks';
import { IThreadService } from 'vs/workbench/services/thread/common/threadService';
import { MainContext, MainThreadTaskShape, ExtHostTaskShape } from 'vs/workbench/api/node/extHost.protocol';
import { MainContext, MainThreadTaskShape, ExtHostTaskShape, IMainContext } from 'vs/workbench/api/node/extHost.protocol';
import * as types from 'vs/workbench/api/node/extHostTypes';
import * as vscode from 'vscode';
@@ -396,15 +395,14 @@ interface HandlerData {
extension: IExtensionDescription;
}
export class ExtHostTask extends ExtHostTaskShape {
export class ExtHostTask implements ExtHostTaskShape {
private _proxy: MainThreadTaskShape;
private _handleCounter: number;
private _handlers: Map<number, HandlerData>;
constructor(threadService: IThreadService) {
super();
this._proxy = threadService.get(MainContext.MainThreadTask);
constructor(mainContext: IMainContext) {
this._proxy = mainContext.get(MainContext.MainThreadTask);
this._handleCounter = 0;
this._handlers = new Map<number, HandlerData>();
};

View File

@@ -1,47 +0,0 @@
/*---------------------------------------------------------------------------------------------
* 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 { notImplemented } from 'vs/base/common/errors';
import { TPromise } from 'vs/base/common/winjs.base';
import { ITelemetryService, ITelemetryInfo } from 'vs/platform/telemetry/common/telemetry';
import { IThreadService } from 'vs/workbench/services/thread/common/threadService';
import { MainContext, MainThreadTelemetryShape } from './extHost.protocol';
export class RemoteTelemetryService implements ITelemetryService {
_serviceBrand: any;
private _name: string;
private _proxy: MainThreadTelemetryShape;
constructor(name: string, threadService: IThreadService) {
this._name = name;
this._proxy = threadService.get(MainContext.MainThreadTelemetry);
}
get isOptedIn(): boolean {
throw notImplemented();
}
getTelemetryInfo(): TPromise<ITelemetryInfo> {
return this._proxy.$getTelemetryInfo();
}
publicLog(eventName: string, data?: any): TPromise<void> {
data = data || Object.create(null);
data[this._name] = true;
this._proxy.$publicLog(eventName, data);
return TPromise.as(null);
}
timedPublicLog(): any {
throw notImplemented();
}
addTelemetryAppender(): any {
throw notImplemented();
}
}

View File

@@ -7,8 +7,7 @@
import vscode = require('vscode');
import { TPromise, TValueCallback } from 'vs/base/common/winjs.base';
import Event, { Emitter } from 'vs/base/common/event';
import { ExtHostTerminalServiceShape, MainContext, MainThreadTerminalServiceShape } from './extHost.protocol';
import { IThreadService } from 'vs/workbench/services/thread/common/threadService';
import { ExtHostTerminalServiceShape, MainContext, MainThreadTerminalServiceShape, IMainContext } from './extHost.protocol';
export class ExtHostTerminal implements vscode.Terminal {
@@ -101,9 +100,9 @@ export class ExtHostTerminalService implements ExtHostTerminalServiceShape {
private _proxy: MainThreadTerminalServiceShape;
private _terminals: ExtHostTerminal[];
constructor(threadService: IThreadService) {
constructor(mainContext: IMainContext) {
this._onDidCloseTerminal = new Emitter<vscode.Terminal>();
this._proxy = threadService.get(MainContext.MainThreadTerminalService);
this._proxy = mainContext.get(MainContext.MainThreadTerminalService);
this._terminals = [];
}

View File

@@ -6,17 +6,19 @@
import { ok } from 'vs/base/common/assert';
import { readonly, illegalArgument } from 'vs/base/common/errors';
import { readonly, illegalArgument, V8CallSite } from 'vs/base/common/errors';
import { IdGenerator } from 'vs/base/common/idGenerator';
import { TPromise } from 'vs/base/common/winjs.base';
import { ExtHostDocumentData } from 'vs/workbench/api/node/extHostDocumentData';
import { Selection, Range, Position, EndOfLine, TextEditorRevealType, TextEditorLineNumbersStyle, SnippetString } from './extHostTypes';
import { ISingleEditOperation } from 'vs/editor/common/editorCommon';
import * as TypeConverters from './extHostTypeConverters';
import { MainThreadEditorsShape, IResolvedTextEditorConfiguration, ITextEditorConfigurationUpdate } from './extHost.protocol';
import { MainThreadEditorsShape, MainThreadTelemetryShape, IResolvedTextEditorConfiguration, ITextEditorConfigurationUpdate } from './extHost.protocol';
import * as vscode from 'vscode';
import { TextEditorCursorStyle } from 'vs/editor/common/config/editorOptions';
import { IRange } from 'vs/editor/common/core/range';
import { containsCommandLink } from 'vs/base/common/htmlContent';
import { ExtHostExtensionService } from 'vs/workbench/api/node/extHostExtensionService';
export class TextEditorDecorationType implements vscode.TextEditorDecorationType {
@@ -542,12 +544,78 @@ export class ExtHostTextEditor implements vscode.TextEditor {
return TPromise.as(undefined);
}
return callback().then(() => this, err => {
console.warn(err);
return undefined;
if (!(err instanceof Error && err.name === 'DISPOSED')) {
console.warn(err);
}
return null;
});
}
}
export class ExtHostTextEditor2 extends ExtHostTextEditor {
constructor(
private readonly _extHostExtensions: ExtHostExtensionService,
private readonly _mainThreadTelemetry: MainThreadTelemetryShape,
proxy: MainThreadEditorsShape,
id: string,
document: ExtHostDocumentData,
selections: Selection[],
options: IResolvedTextEditorConfiguration,
viewColumn: vscode.ViewColumn
) {
super(proxy, id, document, selections, options, viewColumn);
}
setDecorations(decorationType: vscode.TextEditorDecorationType, rangesOrOptions: Range[] | vscode.DecorationOptions[]): void {
// (1) find out if this decoration is important for us
let usesCommandLink = false;
outer: for (const rangeOrOption of rangesOrOptions) {
if (Range.isRange(rangeOrOption)) {
break;
}
if (typeof rangeOrOption.hoverMessage === 'string' && containsCommandLink(rangeOrOption.hoverMessage)) {
usesCommandLink = true;
break;
} else if (Array.isArray(rangeOrOption.hoverMessage)) {
for (const message of rangeOrOption.hoverMessage) {
if (typeof message === 'string' && containsCommandLink(message)) {
usesCommandLink = true;
break outer;
}
}
}
}
// (2) send event for important decorations
if (usesCommandLink) {
let tag = new Error();
this._extHostExtensions.getExtensionPathIndex().then(index => {
const oldHandler = (<any>Error).prepareStackTrace;
(<any>Error).prepareStackTrace = (error: Error, stackTrace: V8CallSite[]) => {
for (const call of stackTrace) {
const extension = index.findSubstr(call.getFileName());
if (extension) {
this._mainThreadTelemetry.$publicLog('usesCommandLink', {
extension: extension.id,
from: 'decoration',
});
return;
}
}
};
// it all happens here...
// tslint:disable-next-line:no-unused-expression
tag.stack;
(<any>Error).prepareStackTrace = oldHandler;
});
}
// (3) do it
super.setDecorations(decorationType, rangesOrOptions);
}
}
function warnOnError(promise: TPromise<any>): void {
promise.then(null, (err) => {
console.warn(err);

View File

@@ -8,16 +8,15 @@ import URI from 'vs/base/common/uri';
import Event, { Emitter } from 'vs/base/common/event';
import { toThenable } from 'vs/base/common/async';
import { TPromise } from 'vs/base/common/winjs.base';
import { IThreadService } from 'vs/workbench/services/thread/common/threadService';
import { TextEditorSelectionChangeKind } from './extHostTypes';
import * as TypeConverters from './extHostTypeConverters';
import { TextEditorDecorationType, ExtHostTextEditor } from './extHostTextEditor';
import { ExtHostDocumentsAndEditors } from './extHostDocumentsAndEditors';
import { Position as EditorPosition } from 'vs/platform/editor/common/editor';
import { MainContext, MainThreadEditorsShape, ExtHostEditorsShape, ITextDocumentShowOptions, ITextEditorPositionData, IResolvedTextEditorConfiguration, ISelectionChangeEvent } from './extHost.protocol';
import { MainContext, MainThreadEditorsShape, ExtHostEditorsShape, ITextDocumentShowOptions, ITextEditorPositionData, IResolvedTextEditorConfiguration, ISelectionChangeEvent, IMainContext } from './extHost.protocol';
import * as vscode from 'vscode';
export class ExtHostEditors extends ExtHostEditorsShape {
export class ExtHostEditors implements ExtHostEditorsShape {
private readonly _onDidChangeTextEditorSelection = new Emitter<vscode.TextEditorSelectionChangeEvent>();
private readonly _onDidChangeTextEditorOptions = new Emitter<vscode.TextEditorOptionsChangeEvent>();
@@ -36,11 +35,10 @@ export class ExtHostEditors extends ExtHostEditorsShape {
private _extHostDocumentsAndEditors: ExtHostDocumentsAndEditors;
constructor(
threadService: IThreadService,
mainContext: IMainContext,
extHostDocumentsAndEditors: ExtHostDocumentsAndEditors,
) {
super();
this._proxy = threadService.get(MainContext.MainThreadEditors);
this._proxy = mainContext.get(MainContext.MainThreadEditors);
this._extHostDocumentsAndEditors = extHostDocumentsAndEditors;
this._extHostDocumentsAndEditors.onDidChangeVisibleTextEditors(e => this._onDidChangeVisibleTextEditors.fire(e));

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';
@@ -18,17 +19,14 @@ import { asWinJsPromise } from 'vs/base/common/async';
type TreeItemHandle = number;
export class ExtHostTreeViews extends ExtHostTreeViewsShape {
export class ExtHostTreeViews implements 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 +78,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 +111,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

@@ -16,6 +16,7 @@ import { SaveReason } from 'vs/workbench/services/textfile/common/textfiles';
import { IPosition } from 'vs/editor/common/core/position';
import { IRange } from 'vs/editor/common/core/range';
import { ISelection } from 'vs/editor/common/core/selection';
import * as htmlContent from 'vs/base/common/htmlContent';
export interface PositionLike {
line: number;
@@ -143,12 +144,35 @@ function isDecorationOptionsArr(something: vscode.Range[] | vscode.DecorationOpt
return isDecorationOptions(something[0]) ? true : false;
}
export namespace MarkdownString {
export function fromMany(markup: (vscode.MarkdownString | vscode.MarkedString)[]): htmlContent.IMarkdownString[] {
return markup.map(MarkdownString.from);
}
export function from(markup: vscode.MarkdownString | vscode.MarkedString): htmlContent.IMarkdownString {
if (htmlContent.isMarkdownString(markup)) {
return markup;
} else if (typeof markup === 'string' || !markup) {
return { value: <string>markup || '', isTrusted: true };
} else {
const { language, value } = markup;
return { value: '```' + language + '\n' + value + '\n```' };
}
}
export function to(value: htmlContent.IMarkdownString): vscode.MarkdownString {
const ret = new htmlContent.MarkdownString(value.value);
ret.isTrusted = value.isTrusted;
return ret;
}
}
export function fromRangeOrRangeWithMessage(ranges: vscode.Range[] | vscode.DecorationOptions[]): IDecorationOptions[] {
if (isDecorationOptionsArr(ranges)) {
return ranges.map((r): IDecorationOptions => {
return ranges.map(r => {
return {
range: fromRange(r.range),
hoverMessage: r.hoverMessage,
hoverMessage: Array.isArray(r.hoverMessage) ? MarkdownString.fromMany(r.hoverMessage) : r.hoverMessage && MarkdownString.from(r.hoverMessage),
renderOptions: <any> /* URI vs Uri */r.renderOptions
};
});
@@ -256,12 +280,12 @@ export const location = {
export function fromHover(hover: vscode.Hover): modes.Hover {
return <modes.Hover>{
range: fromRange(hover.range),
contents: hover.contents
contents: MarkdownString.fromMany(hover.contents)
};
}
export function toHover(info: modes.Hover): types.Hover {
return new types.Hover(info.contents, toRange(info.range));
return new types.Hover(info.contents.map(MarkdownString.to), toRange(info.range));
}
export function toDocumentHighlight(occurrence: modes.DocumentHighlight): types.DocumentHighlight {

View File

@@ -7,8 +7,10 @@
import * as crypto from 'crypto';
import URI from 'vs/base/common/uri';
import { Color as BaseColor, HSLA } from 'vs/base/common/color';
import { illegalArgument } from 'vs/base/common/errors';
import * as vscode from 'vscode';
import { isMarkdownString } from 'vs/base/common/htmlContent';
export class Disposable {
@@ -697,16 +699,20 @@ export class Diagnostic {
export class Hover {
public contents: vscode.MarkedString[];
public contents: vscode.MarkdownString[] | vscode.MarkedString[];
public range: Range;
constructor(contents: vscode.MarkedString | vscode.MarkedString[], range?: Range) {
constructor(
contents: vscode.MarkdownString | vscode.MarkedString | vscode.MarkdownString[] | vscode.MarkedString[],
range?: Range
) {
if (!contents) {
throw new Error('Illegal argument, contents must be defined');
}
if (Array.isArray(contents)) {
this.contents = contents;
this.contents = <vscode.MarkdownString[] | vscode.MarkedString[]>contents;
} else if (isMarkdownString(contents)) {
this.contents = [contents];
} else {
this.contents = [contents];
}
@@ -1013,6 +1019,59 @@ export class DocumentLink {
}
}
export class Color {
readonly red: number;
readonly green: number;
readonly blue: number;
readonly alpha: number;
constructor(red: number, green: number, blue: number, alpha: number) {
this.red = red;
this.green = green;
this.blue = blue;
this.alpha = alpha;
}
static fromHSLA(hue: number, saturation: number, luminance: number, alpha: number): Color {
const color = new BaseColor(new HSLA(hue, saturation, luminance, alpha)).rgba;
return new Color(color.r, color.g, color.b, color.a);
}
static fromHex(hex: string): Color | null {
let baseColor = BaseColor.Format.CSS.parseHex(hex);
if (baseColor) {
const rgba = baseColor.rgba;
return new Color(rgba.r, rgba.g, rgba.b, rgba.a);
}
return null;
}
}
export type IColorFormat = string | { opaque: string, transparent: string };
export class ColorRange {
range: Range;
color: Color;
availableFormats: IColorFormat[];
constructor(range: Range, color: Color, availableFormats: IColorFormat[]) {
if (color && !(color instanceof Color)) {
throw illegalArgument('color');
}
if (availableFormats && !Array.isArray(availableFormats)) {
throw illegalArgument('availableFormats');
}
if (!Range.isRange(range) || range.isEmpty) {
throw illegalArgument('range');
}
this.range = range;
this.color = color;
this.availableFormats = availableFormats;
}
}
export enum TaskRevealKind {
Always = 1,
@@ -1316,3 +1375,11 @@ export class ThemeColor {
this.id = id;
}
}
export enum ConfigurationTarget {
Global = 1,
Workspace = 2,
WorkspaceFolder = 3
}

View File

@@ -10,13 +10,14 @@ import { normalize } from 'vs/base/common/paths';
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';
import { TPromise } from 'vs/base/common/winjs.base';
import { fromRange, EndOfLine } from 'vs/workbench/api/node/extHostTypeConverters';
import { IWorkspaceData, ExtHostWorkspaceShape, MainContext, MainThreadWorkspaceShape } from './extHost.protocol';
import { IWorkspaceData, ExtHostWorkspaceShape, MainContext, MainThreadWorkspaceShape, IMainContext } 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 {
@@ -64,7 +65,7 @@ class Workspace2 extends Workspace {
}
}
export class ExtHostWorkspace extends ExtHostWorkspaceShape {
export class ExtHostWorkspace implements ExtHostWorkspaceShape {
private static _requestIdPool = 0;
@@ -74,9 +75,8 @@ export class ExtHostWorkspace extends ExtHostWorkspaceShape {
readonly onDidChangeWorkspace: Event<vscode.WorkspaceFoldersChangeEvent> = this._onDidChangeWorkspace.event;
constructor(threadService: IThreadService, data: IWorkspaceData) {
super();
this._proxy = threadService.get(MainContext.MainThreadWorkspace);
constructor(mainContext: IMainContext, data: IWorkspaceData) {
this._proxy = mainContext.get(MainContext.MainThreadWorkspace);
this._workspace = Workspace2.fromData(data);
}
@@ -115,7 +115,7 @@ export class ExtHostWorkspace extends ExtHostWorkspaceShape {
return roots[0].fsPath;
}
getRelativePath(pathOrUri: string | vscode.Uri): string {
getRelativePath(pathOrUri: string | vscode.Uri, includeWorkspace?: boolean): string {
let path: string;
if (typeof pathOrUri === 'string') {
@@ -137,8 +137,12 @@ export class ExtHostWorkspace extends ExtHostWorkspaceShape {
return normalize(path);
}
if (typeof includeWorkspace === 'undefined') {
includeWorkspace = this.workspace.roots.length > 1;
}
let result = relative(folder.uri.fsPath, path);
if (this.workspace.roots.length > 1) {
if (includeWorkspace) {
result = `${folder.name}/${result}`;
}
return normalize(result);
@@ -200,4 +204,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));
}
}