/*--------------------------------------------------------------------------------------------- * 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 { Emitter, mapEvent } 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 { ExtHostDocumentSaveParticipant } from 'vs/workbench/api/node/extHostDocumentSaveParticipant'; import { ExtHostConfiguration } from 'vs/workbench/api/node/extHostConfiguration'; import { ExtHostDiagnostics } from 'vs/workbench/api/node/extHostDiagnostics'; import { ExtHostTreeViews } from 'vs/workbench/api/node/extHostTreeViews'; import { ExtHostWorkspace } from 'vs/workbench/api/node/extHostWorkspace'; import { ExtHostQuickOpen } from 'vs/workbench/api/node/extHostQuickOpen'; import { ExtHostProgress } from 'vs/workbench/api/node/extHostProgress'; import { ExtHostSCM } from 'vs/workbench/api/node/extHostSCM'; import { ExtHostHeapService } from 'vs/workbench/api/node/extHostHeapService'; import { ExtHostStatusBar } from 'vs/workbench/api/node/extHostStatusBar'; import { ExtHostCommands } from 'vs/workbench/api/node/extHostCommands'; import { ExtHostOutputService } from 'vs/workbench/api/node/extHostOutputService'; import { ExtHostTerminalService } from 'vs/workbench/api/node/extHostTerminalService'; import { ExtHostMessageService } from 'vs/workbench/api/node/extHostMessageService'; import { ExtHostEditors } from 'vs/workbench/api/node/extHostTextEditors'; import { ExtHostLanguages } from 'vs/workbench/api/node/extHostLanguages'; import { ExtHostLanguageFeatures } from 'vs/workbench/api/node/extHostLanguageFeatures'; import { ExtHostApiCommands } from 'vs/workbench/api/node/extHostApiCommands'; import { ExtHostTask } from 'vs/workbench/api/node/extHostTask'; import * as extHostTypes from 'vs/workbench/api/node/extHostTypes'; import URI from 'vs/base/common/uri'; import Severity from 'vs/base/common/severity'; 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 { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; 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 * as languageConfiguration from 'vs/editor/common/modes/languageConfiguration'; import { TextEditorCursorStyle } from 'vs/editor/common/config/editorOptions'; export interface IExtensionApiFactory { (extension: IExtensionDescription): typeof vscode; } function proposedApiFunction(extension: IExtensionDescription, fn: T): T { if (extension.enableProposedApi) { return fn; } else { return (() => { throw new Error(`[${extension.id}]: Proposed API is only available when running out of dev or with the following command line switch: --enable-proposed-api ${extension.id}`); }); } } function proposed(extension: IExtensionDescription): Function { return (target: any, key: string, descriptor: any) => { let fnKey: string = null; let fn: Function = null; if (typeof descriptor.value === 'function') { fnKey = 'value'; fn = descriptor.value; } else if (typeof descriptor.get === 'function') { fnKey = 'get'; fn = descriptor.get; } if (!fn) { throw new Error('not supported'); } if (extension.enableProposedApi) { return; } descriptor[fnKey] = () => { throw new Error(`${extension.id} cannot access proposed api`); }; }; } /** * This method instantiates and returns the extension API surface */ export function createApiFactory( initData: IInitData, threadService: IThreadService, extensionService: ExtHostExtensionService, contextService: IWorkspaceContextService, telemetryService: ITelemetryService ): IExtensionApiFactory { // Addressable instances const col = new InstanceCollection(); const extHostHeapService = col.define(ExtHostContext.ExtHostHeapService).set(new ExtHostHeapService()); const extHostDocumentsAndEditors = col.define(ExtHostContext.ExtHostDocumentsAndEditors).set(new ExtHostDocumentsAndEditors(threadService)); const extHostDocuments = col.define(ExtHostContext.ExtHostDocuments).set(new ExtHostDocuments(threadService, extHostDocumentsAndEditors)); const extHostDocumentSaveParticipant = col.define(ExtHostContext.ExtHostDocumentSaveParticipant).set(new ExtHostDocumentSaveParticipant(extHostDocuments, threadService.get(MainContext.MainThreadWorkspace))); const extHostEditors = col.define(ExtHostContext.ExtHostEditors).set(new ExtHostEditors(threadService, extHostDocumentsAndEditors)); const extHostCommands = col.define(ExtHostContext.ExtHostCommands).set(new ExtHostCommands(threadService, extHostHeapService)); const extHostTreeViews = col.define(ExtHostContext.ExtHostTreeViews).set(new ExtHostTreeViews(threadService, extHostCommands)); const extHostConfiguration = col.define(ExtHostContext.ExtHostConfiguration).set(new ExtHostConfiguration(threadService.get(MainContext.MainThreadConfiguration), initData.configuration)); const extHostDiagnostics = col.define(ExtHostContext.ExtHostDiagnostics).set(new ExtHostDiagnostics(threadService)); const languageFeatures = col.define(ExtHostContext.ExtHostLanguageFeatures).set(new ExtHostLanguageFeatures(threadService, extHostDocuments, extHostCommands, extHostHeapService, extHostDiagnostics)); const extHostFileSystemEvent = col.define(ExtHostContext.ExtHostFileSystemEventService).set(new ExtHostFileSystemEventService()); const extHostQuickOpen = col.define(ExtHostContext.ExtHostQuickOpen).set(new ExtHostQuickOpen(threadService)); const extHostTerminalService = col.define(ExtHostContext.ExtHostTerminalService).set(new ExtHostTerminalService(threadService)); const extHostSCM = col.define(ExtHostContext.ExtHostSCM).set(new ExtHostSCM(threadService, extHostCommands)); const extHostTask = col.define(ExtHostContext.ExtHostTask).set(new ExtHostTask(threadService)); col.define(ExtHostContext.ExtHostExtensionService).set(extensionService); col.finish(false, threadService); // Other instances const extHostMessageService = new ExtHostMessageService(threadService); const extHostStatusBar = new ExtHostStatusBar(threadService); const extHostProgress = new ExtHostProgress(threadService.get(MainContext.MainThreadProgress)); const extHostOutputService = new ExtHostOutputService(threadService); const workspacePath = contextService.hasWorkspace() ? contextService.getWorkspace().resource.fsPath : undefined; const extHostWorkspace = new ExtHostWorkspace(threadService, workspacePath); const extHostLanguages = new ExtHostLanguages(threadService); // Register API-ish commands ExtHostApiCommands.register(extHostCommands); return function (extension: IExtensionDescription): typeof vscode { if (extension.enableProposedApi && !extension.isBuiltin) { if ( !initData.environment.enableProposedApiForAll && initData.environment.enableProposedApiFor.indexOf(extension.id) < 0 ) { extension.enableProposedApi = false; console.error(`Extension '${extension.id} cannot use PROPOSED API (must started out of dev or enabled via --enable-proposed-api)`); } else { // proposed api is available when developing or when an extension was explicitly // spelled out via a command line argument console.warn(`Extension '${extension.id}' uses PROPOSED API which is subject to change and removal without notice.`); } } class Commands { registerCommand(id: string, command: (...args: any[]) => T | Thenable, thisArgs?: any): vscode.Disposable { return extHostCommands.registerCommand(id, command, thisArgs); } registerTextEditorCommand(id: string, callback: (textEditor: vscode.TextEditor, edit: vscode.TextEditorEdit, ...args: any[]) => void, thisArg?: any): vscode.Disposable { return extHostCommands.registerCommand(id, (...args: any[]) => { let activeTextEditor = extHostEditors.getActiveTextEditor(); if (!activeTextEditor) { console.warn('Cannot execute ' + id + ' because there is no active text editor.'); return undefined; } return activeTextEditor.edit((edit: vscode.TextEditorEdit) => { args.unshift(activeTextEditor, edit); callback.apply(thisArg, args); }).then((result) => { if (!result) { console.warn('Edits from command ' + id + ' were not applied.'); } }, (err) => { console.warn('An error occured while running command ' + id, err); }); }); } @proposed(extension) registerDiffInformationCommand(id: string, callback: (diff: vscode.LineChange[], ...args: any[]) => any, thisArg?: any): vscode.Disposable { return extHostCommands.registerCommand(id, async (...args: any[]) => { let activeTextEditor = extHostEditors.getActiveTextEditor(); if (!activeTextEditor) { console.warn('Cannot execute ' + id + ' because there is no active text editor.'); return undefined; } const diff = await extHostEditors.getDiffInformation(activeTextEditor.id); callback.apply(thisArg, [diff, ...args]); }); } executeCommand(id: string, ...args: any[]): Thenable { return extHostCommands.executeCommand(id, ...args); } getCommands(filterInternal: boolean = false): Thenable { return extHostCommands.getCommands(filterInternal); } } // namespace: commands const commands: typeof vscode.commands = new Commands(); // namespace: env const env: typeof vscode.env = Object.freeze({ get machineId() { return initData.telemetryInfo.machineId; }, get sessionId() { return initData.telemetryInfo.sessionId; }, get language() { return Platform.language; }, get appName() { return product.nameLong; } }); // namespace: extensions const extensions: typeof vscode.extensions = { getExtension(extensionId: string): Extension { let desc = extensionService.getExtensionDescription(extensionId); if (desc) { return new Extension(extensionService, desc); } return undefined; }, get all(): Extension[] { return extensionService.getAllExtensionDescriptions().map((desc) => new Extension(extensionService, desc)); } }; // namespace: languages const languages: typeof vscode.languages = { createDiagnosticCollection(name?: string): vscode.DiagnosticCollection { return extHostDiagnostics.createDiagnosticCollection(name); }, getLanguages(): TPromise { return extHostLanguages.getLanguages(); }, match(selector: vscode.DocumentSelector, document: vscode.TextDocument): number { return score(selector, document.uri, document.languageId); }, registerCodeActionsProvider(selector: vscode.DocumentSelector, provider: vscode.CodeActionProvider): vscode.Disposable { return languageFeatures.registerCodeActionProvider(selector, provider); }, registerCodeLensProvider(selector: vscode.DocumentSelector, provider: vscode.CodeLensProvider): vscode.Disposable { return languageFeatures.registerCodeLensProvider(selector, provider); }, registerDefinitionProvider(selector: vscode.DocumentSelector, provider: vscode.DefinitionProvider): vscode.Disposable { return languageFeatures.registerDefinitionProvider(selector, provider); }, registerImplementationProvider(selector: vscode.DocumentSelector, provider: vscode.ImplementationProvider): vscode.Disposable { return languageFeatures.registerImplementationProvider(selector, provider); }, registerTypeDefinitionProvider(selector: vscode.DocumentSelector, provider: vscode.TypeDefinitionProvider): vscode.Disposable { return languageFeatures.registerTypeDefinitionProvider(selector, provider); }, registerHoverProvider(selector: vscode.DocumentSelector, provider: vscode.HoverProvider): vscode.Disposable { return languageFeatures.registerHoverProvider(selector, provider); }, registerDocumentHighlightProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentHighlightProvider): vscode.Disposable { return languageFeatures.registerDocumentHighlightProvider(selector, provider); }, registerReferenceProvider(selector: vscode.DocumentSelector, provider: vscode.ReferenceProvider): vscode.Disposable { return languageFeatures.registerReferenceProvider(selector, provider); }, registerRenameProvider(selector: vscode.DocumentSelector, provider: vscode.RenameProvider): vscode.Disposable { return languageFeatures.registerRenameProvider(selector, provider); }, registerDocumentSymbolProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentSymbolProvider): vscode.Disposable { return languageFeatures.registerDocumentSymbolProvider(selector, provider); }, registerWorkspaceSymbolProvider(provider: vscode.WorkspaceSymbolProvider): vscode.Disposable { return languageFeatures.registerWorkspaceSymbolProvider(provider); }, registerDocumentFormattingEditProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentFormattingEditProvider): vscode.Disposable { return languageFeatures.registerDocumentFormattingEditProvider(selector, provider); }, registerDocumentRangeFormattingEditProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentRangeFormattingEditProvider): vscode.Disposable { return languageFeatures.registerDocumentRangeFormattingEditProvider(selector, provider); }, registerOnTypeFormattingEditProvider(selector: vscode.DocumentSelector, provider: vscode.OnTypeFormattingEditProvider, firstTriggerCharacter: string, ...moreTriggerCharacters: string[]): vscode.Disposable { return languageFeatures.registerOnTypeFormattingEditProvider(selector, provider, [firstTriggerCharacter].concat(moreTriggerCharacters)); }, registerSignatureHelpProvider(selector: vscode.DocumentSelector, provider: vscode.SignatureHelpProvider, ...triggerCharacters: string[]): vscode.Disposable { return languageFeatures.registerSignatureHelpProvider(selector, provider, triggerCharacters); }, registerCompletionItemProvider(selector: vscode.DocumentSelector, provider: vscode.CompletionItemProvider, ...triggerCharacters: string[]): vscode.Disposable { return languageFeatures.registerCompletionItemProvider(selector, provider, triggerCharacters); }, registerDocumentLinkProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentLinkProvider): vscode.Disposable { return languageFeatures.registerDocumentLinkProvider(selector, provider); }, setLanguageConfiguration: (language: string, configuration: vscode.LanguageConfiguration): vscode.Disposable => { return languageFeatures.setLanguageConfiguration(language, configuration); } }; // namespace: window const window: typeof vscode.window = { get activeTextEditor() { return extHostEditors.getActiveTextEditor(); }, get visibleTextEditors() { return extHostEditors.getVisibleTextEditors(); }, showTextDocument(document: vscode.TextDocument, columnOrOptions?: vscode.ViewColumn | vscode.TextDocumentShowOptions, preserveFocus?: boolean): TPromise { return extHostEditors.showTextDocument(document, columnOrOptions, preserveFocus); }, createTextEditorDecorationType(options: vscode.DecorationRenderOptions): vscode.TextEditorDecorationType { return extHostEditors.createTextEditorDecorationType(options); }, onDidChangeActiveTextEditor(listener, thisArg?, disposables?) { return extHostEditors.onDidChangeActiveTextEditor(listener, thisArg, disposables); }, onDidChangeVisibleTextEditors(listener, thisArg, disposables) { return extHostEditors.onDidChangeVisibleTextEditors(listener, thisArg, disposables); }, onDidChangeTextEditorSelection(listener: (e: vscode.TextEditorSelectionChangeEvent) => any, thisArgs?: any, disposables?: extHostTypes.Disposable[]) { return extHostEditors.onDidChangeTextEditorSelection(listener, thisArgs, disposables); }, onDidChangeTextEditorOptions(listener: (e: vscode.TextEditorOptionsChangeEvent) => any, thisArgs?: any, disposables?: extHostTypes.Disposable[]) { return extHostEditors.onDidChangeTextEditorOptions(listener, thisArgs, disposables); }, onDidChangeTextEditorViewColumn(listener, thisArg?, disposables?) { return extHostEditors.onDidChangeTextEditorViewColumn(listener, thisArg, disposables); }, onDidCloseTerminal(listener, thisArg?, disposables?) { return extHostTerminalService.onDidCloseTerminal(listener, thisArg, disposables); }, showInformationMessage(message, first, ...rest) { return extHostMessageService.showMessage(Severity.Info, message, first, rest); }, showWarningMessage(message, first, ...rest) { return extHostMessageService.showMessage(Severity.Warning, message, first, rest); }, showErrorMessage(message, first, ...rest) { return extHostMessageService.showMessage(Severity.Error, message, first, rest); }, showQuickPick(items: any, options: vscode.QuickPickOptions, token?: vscode.CancellationToken) { return extHostQuickOpen.showQuickPick(items, options, token); }, showInputBox(options?: vscode.InputBoxOptions, token?: vscode.CancellationToken) { return extHostQuickOpen.showInput(options, token); }, createStatusBarItem(position?: vscode.StatusBarAlignment, priority?: number): vscode.StatusBarItem { return extHostStatusBar.createStatusBarEntry(extension.id, position, priority); }, setStatusBarMessage(text: string, timeoutOrThenable?: number | Thenable): vscode.Disposable { return extHostStatusBar.setStatusBarMessage(text, timeoutOrThenable); }, withScmProgress(task: (progress: vscode.Progress) => Thenable) { console.warn(`[Deprecation Warning] function 'withScmProgress' is deprecated and should no longer be used. Use 'withProgress' instead.`); return extHostProgress.withProgress(extension, { location: extHostTypes.ProgressLocation.SourceControl }, task); }, withProgress(options: vscode.ProgressOptions, task: (progress: vscode.Progress<{ message?: string; percentage?: number }>) => Thenable) { return extHostProgress.withProgress(extension, options, task); }, createOutputChannel(name: string): vscode.OutputChannel { return extHostOutputService.createOutputChannel(name); }, createTerminal(nameOrOptions: vscode.TerminalOptions | string, shellPath?: string, shellArgs?: string[]): vscode.Terminal { if (typeof nameOrOptions === 'object') { return extHostTerminalService.createTerminalFromOptions(nameOrOptions); } return extHostTerminalService.createTerminal(nameOrOptions, shellPath, shellArgs); }, // proposed API sampleFunction: proposedApiFunction(extension, () => { return extHostMessageService.showMessage(Severity.Info, 'Hello Proposed Api!', {}, []); }), registerTreeDataProviderForView: proposedApiFunction(extension, (viewId: string, treeDataProvider: vscode.TreeDataProvider): vscode.Disposable => { return extHostTreeViews.registerTreeDataProviderForView(viewId, treeDataProvider); }) }; // namespace: workspace const workspace: typeof vscode.workspace = { get rootPath() { return extHostWorkspace.getPath(); }, set rootPath(value) { throw errors.readonly(); }, asRelativePath: (pathOrUri) => { return extHostWorkspace.getRelativePath(pathOrUri); }, findFiles: (include, exclude, maxResults?, token?) => { return extHostWorkspace.findFiles(include, exclude, maxResults, token); }, saveAll: (includeUntitled?) => { return extHostWorkspace.saveAll(includeUntitled); }, applyEdit(edit: vscode.WorkspaceEdit): TPromise { return extHostWorkspace.appyEdit(edit); }, createFileSystemWatcher: (pattern, ignoreCreate, ignoreChange, ignoreDelete): vscode.FileSystemWatcher => { return extHostFileSystemEvent.createFileSystemWatcher(pattern, ignoreCreate, ignoreChange, ignoreDelete); }, get textDocuments() { return extHostDocuments.getAllDocumentData().map(data => data.document); }, set textDocuments(value) { throw errors.readonly(); }, openTextDocument(uriOrFileNameOrOptions?: vscode.Uri | string | { language?: string; content?: string; }) { let uriPromise: TPromise; let options = uriOrFileNameOrOptions as { language?: string; content?: string; }; if (!options || typeof options.language === 'string') { uriPromise = extHostDocuments.createDocumentData(options); } else if (typeof uriOrFileNameOrOptions === 'string') { uriPromise = TPromise.as(URI.file(uriOrFileNameOrOptions)); } else if (uriOrFileNameOrOptions instanceof URI) { uriPromise = TPromise.as(uriOrFileNameOrOptions); } else { throw new Error('illegal argument - uriOrFileNameOrOptions'); } return uriPromise.then(uri => { return extHostDocuments.ensureDocumentData(uri).then(() => { const data = extHostDocuments.getDocumentData(uri); return data && data.document; }); }); }, registerTextDocumentContentProvider(scheme: string, provider: vscode.TextDocumentContentProvider) { return extHostDocuments.registerTextDocumentContentProvider(scheme, provider); }, onDidOpenTextDocument: (listener, thisArgs?, disposables?) => { return extHostDocuments.onDidAddDocument(listener, thisArgs, disposables); }, onDidCloseTextDocument: (listener, thisArgs?, disposables?) => { return extHostDocuments.onDidRemoveDocument(listener, thisArgs, disposables); }, onDidChangeTextDocument: (listener, thisArgs?, disposables?) => { return extHostDocuments.onDidChangeDocument(listener, thisArgs, disposables); }, onDidSaveTextDocument: (listener, thisArgs?, disposables?) => { return extHostDocuments.onDidSaveDocument(listener, thisArgs, disposables); }, onWillSaveTextDocument: (listener, thisArgs?, disposables?) => { return extHostDocumentSaveParticipant.onWillSaveTextDocumentEvent(listener, thisArgs, disposables); }, onDidChangeConfiguration: (listener: () => any, thisArgs?: any, disposables?: extHostTypes.Disposable[]) => { return extHostConfiguration.onDidChangeConfiguration(listener, thisArgs, disposables); }, getConfiguration: (section?: string): vscode.WorkspaceConfiguration => { return extHostConfiguration.getConfiguration(section); }, registerTaskProvider: (provider: vscode.TaskProvider) => { return extHostTask.registerTaskProvider(extension, provider); } }; class SCM { get activeSourceControl() { return extHostSCM.activeProvider; } get onDidChangeActiveSourceControl() { return extHostSCM.onDidChangeActiveProvider; } get inputBox() { return extHostSCM.inputBox; } get onDidAcceptInputValue() { return mapEvent(extHostSCM.inputBox.onDidAccept, () => extHostSCM.inputBox); } createSourceControl(id: string, label: string) { telemetryService.publicLog('registerSCMProvider', { extensionId: extension.id, providerId: id, providerLabel: label }); return extHostSCM.createSourceControl(id, label); } } // namespace: scm const scm: typeof vscode.scm = new SCM(); return { version: pkg.version, // namespaces commands, env, extensions, languages, window, workspace, scm, // types CancellationTokenSource: CancellationTokenSource, CodeLens: extHostTypes.CodeLens, CompletionItem: extHostTypes.CompletionItem, CompletionItemKind: extHostTypes.CompletionItemKind, CompletionList: extHostTypes.CompletionList, Diagnostic: extHostTypes.Diagnostic, DiagnosticSeverity: extHostTypes.DiagnosticSeverity, Disposable: extHostTypes.Disposable, DocumentHighlight: extHostTypes.DocumentHighlight, DocumentHighlightKind: extHostTypes.DocumentHighlightKind, DocumentLink: extHostTypes.DocumentLink, EndOfLine: extHostTypes.EndOfLine, EventEmitter: Emitter, Hover: extHostTypes.Hover, IndentAction: languageConfiguration.IndentAction, Location: extHostTypes.Location, OverviewRulerLane: EditorCommon.OverviewRulerLane, ParameterInformation: extHostTypes.ParameterInformation, Position: extHostTypes.Position, Range: extHostTypes.Range, Selection: extHostTypes.Selection, SignatureHelp: extHostTypes.SignatureHelp, SignatureInformation: extHostTypes.SignatureInformation, SnippetString: extHostTypes.SnippetString, StatusBarAlignment: extHostTypes.StatusBarAlignment, SymbolInformation: extHostTypes.SymbolInformation, SymbolKind: extHostTypes.SymbolKind, TextDocumentSaveReason: extHostTypes.TextDocumentSaveReason, TextEdit: extHostTypes.TextEdit, TextEditorCursorStyle: TextEditorCursorStyle, TextEditorLineNumbersStyle: extHostTypes.TextEditorLineNumbersStyle, TextEditorRevealType: extHostTypes.TextEditorRevealType, TextEditorSelectionChangeKind: extHostTypes.TextEditorSelectionChangeKind, Uri: URI, ViewColumn: extHostTypes.ViewColumn, WorkspaceEdit: extHostTypes.WorkspaceEdit, ProgressLocation: extHostTypes.ProgressLocation, TreeItemCollapsibleState: extHostTypes.TreeItemCollapsibleState, ThemeColor: extHostTypes.ThemeColor, // functions FileLocationKind: extHostTypes.FileLocationKind, ApplyToKind: extHostTypes.ApplyToKind, RevealKind: extHostTypes.RevealKind, TaskGroup: extHostTypes.TaskGroup, ShellTask: extHostTypes.ShellTask, ProcessTask: extHostTypes.ProcessTask }; }; } class Extension implements vscode.Extension { private _extensionService: ExtHostExtensionService; public id: string; public extensionPath: string; public packageJSON: any; constructor(extensionService: ExtHostExtensionService, description: IExtensionDescription) { this._extensionService = extensionService; this.id = description.id; this.extensionPath = paths.normalize(description.extensionFolderPath, true); this.packageJSON = description; } get isActive(): boolean { return this._extensionService.isActivated(this.id); } get exports(): T { return this._extensionService.get(this.id); } activate(): Thenable { return this._extensionService.activateById(this.id).then(() => this.exports); } } export function initializeExtensionApi(extensionService: ExtHostExtensionService, apiFactory: IExtensionApiFactory): TPromise { return createExtensionPathIndex(extensionService).then(trie => defineAPI(apiFactory, trie)); } function createExtensionPathIndex(extensionService: ExtHostExtensionService): TPromise> { // create trie to enable fast 'filename -> extension id' look up const trie = new TrieMap(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); } function defineAPI(factory: IExtensionApiFactory, extensionPaths: TrieMap): void { // each extension is meant to get its own api implementation const extApiImpl = new Map(); let defaultApiImpl: typeof vscode; const node_module = require.__$__nodeRequire('module'); const original = node_module._load; node_module._load = function load(request, parent, isMain) { if (request !== 'vscode') { return original.apply(this, arguments); } // get extension id from filename and api for extension const ext = extensionPaths.findSubstr(parent.filename); if (ext) { let apiImpl = extApiImpl.get(ext.id); if (!apiImpl) { apiImpl = factory(ext); extApiImpl.set(ext.id, apiImpl); } return apiImpl; } // fall back to a default implementation if (!defaultApiImpl) { defaultApiImpl = factory(nullExtensionDescription); } return defaultApiImpl; }; } const nullExtensionDescription: IExtensionDescription = { id: 'nullExtensionDescription', name: 'Null Extension Description', publisher: 'vscode', activationEvents: undefined, contributes: undefined, enableProposedApi: false, engines: undefined, extensionDependencies: undefined, extensionFolderPath: undefined, isBuiltin: false, main: undefined, version: undefined };