From f1aa0929db61ae84f8677210d44b0dbc09d6a280 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Fri, 9 Aug 2019 16:10:50 +0200 Subject: [PATCH] adopt ext host service world, add dummy implementations for some services --- .../api/common/extHostExtensionService.ts | 3 +- .../api/worker/extHostExtensionService.ts | 55 + .../api/worker/extHostStoragePaths.ts | 23 + .../extensions/worker/extHost.api.impl.ts | 964 ------------------ .../extensions/worker/extHost.services.ts | 51 + .../worker/extHostExtensionService.ts | 826 --------------- .../extensions/worker/extensionHostMain.ts | 154 --- .../extensions/worker/extensionHostWorker.ts | 10 +- 8 files changed, 137 insertions(+), 1949 deletions(-) create mode 100644 src/vs/workbench/api/worker/extHostExtensionService.ts create mode 100644 src/vs/workbench/api/worker/extHostStoragePaths.ts delete mode 100644 src/vs/workbench/services/extensions/worker/extHost.api.impl.ts create mode 100644 src/vs/workbench/services/extensions/worker/extHost.services.ts delete mode 100644 src/vs/workbench/services/extensions/worker/extHostExtensionService.ts delete mode 100644 src/vs/workbench/services/extensions/worker/extensionHostMain.ts diff --git a/src/vs/workbench/api/common/extHostExtensionService.ts b/src/vs/workbench/api/common/extHostExtensionService.ts index 58098d94099..cd25ceb4bba 100644 --- a/src/vs/workbench/api/common/extHostExtensionService.ts +++ b/src/vs/workbench/api/common/extHostExtensionService.ts @@ -385,7 +385,8 @@ export abstract class AbstractExtHostExtensionService implements ExtHostExtensio try { activationTimesBuilder.activateCallStart(); logService.trace(`ExtensionService#_callActivateOptional ${extensionId.value}`); - const activateResult: Promise = extensionModule.activate.apply(global, [context]); + const scope = typeof global === 'object' ? global : self; //todo@joh not so nice + const activateResult: Promise = extensionModule.activate.apply(scope, [context]); activationTimesBuilder.activateCallStop(); activationTimesBuilder.activateResolveStart(); diff --git a/src/vs/workbench/api/worker/extHostExtensionService.ts b/src/vs/workbench/api/worker/extHostExtensionService.ts new file mode 100644 index 00000000000..30d15e39399 --- /dev/null +++ b/src/vs/workbench/api/worker/extHostExtensionService.ts @@ -0,0 +1,55 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { createApiFactoryAndRegisterActors } from 'vs/workbench/api/common/extHost.api.impl'; +import { ExtensionActivationTimesBuilder } from 'vs/workbench/api/common/extHostExtensionActivator'; +import { AbstractExtHostExtensionService } from 'vs/workbench/api/common/extHostExtensionService'; +import { endsWith } from 'vs/base/common/strings'; +import { nullExtensionDescription } from 'vs/workbench/services/extensions/common/extensions'; + +export class ExtHostExtensionService extends AbstractExtHostExtensionService { + + protected async _beforeAlmostReadyToRunExtensions(): Promise { + // initialize API and register actors + const factory = this._instaService.invokeFunction(createApiFactoryAndRegisterActors); + + // globally define the vscode module and share that for all extensions + // todo@joh have an instance per extension, not a shared one.... + const sharedApiInstance = factory(nullExtensionDescription, this._registry, await this._extHostConfiguration.getConfigProvider()); + define('vscode', sharedApiInstance); + } + + protected _loadCommonJSModule(modulePath: string, activationTimesBuilder: ExtensionActivationTimesBuilder): Promise { + // fake commonjs world + const module = { exports: {} }; + //@ts-ignore + self['module'] = module; + //@ts-ignore + self['exports'] = module.exports; + // that's improper but might help extensions that aren't author correctly + // @ts-ignore + self['window'] = self; + + try { + activationTimesBuilder.codeLoadingStart(); + // import the single (!) script, make sure it's a JS-file + const suffix = '.js'; + if (endsWith(modulePath, suffix)) { + importScripts(modulePath); + } else { + importScripts(modulePath + suffix); + } + } finally { + activationTimesBuilder.codeLoadingStop(); + } + + // return what it exported + return Promise.resolve(module.exports as T); + } + + public async $setRemoteEnvironment(env: { [key: string]: string | null }): Promise { + throw new Error('Not supported'); + } +} diff --git a/src/vs/workbench/api/worker/extHostStoragePaths.ts b/src/vs/workbench/api/worker/extHostStoragePaths.ts new file mode 100644 index 00000000000..3d07dff7de0 --- /dev/null +++ b/src/vs/workbench/api/worker/extHostStoragePaths.ts @@ -0,0 +1,23 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { IExtensionStoragePaths } from 'vs/workbench/api/common/extHostStoragePaths'; +import { IExtensionDescription } from 'vs/platform/extensions/common/extensions'; + +export class ExtensionStoragePaths implements IExtensionStoragePaths { + + readonly _serviceBrand: undefined; + + readonly whenReady: Promise = Promise.resolve(); + + //todo@joh -> this isn't proper but also hard to get right... + workspaceValue(_extension: IExtensionDescription): string | undefined { + return ''; + } + + globalValue(_extension: IExtensionDescription): string { + return ''; + } +} diff --git a/src/vs/workbench/services/extensions/worker/extHost.api.impl.ts b/src/vs/workbench/services/extensions/worker/extHost.api.impl.ts deleted file mode 100644 index e0c1f3ad4d1..00000000000 --- a/src/vs/workbench/services/extensions/worker/extHost.api.impl.ts +++ /dev/null @@ -1,964 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import * as nls from 'vs/nls'; -import { CancellationTokenSource } from 'vs/base/common/cancellation'; -import * as errors from 'vs/base/common/errors'; -import { Emitter, Event } from 'vs/base/common/event'; -import * as path from 'vs/base/common/path'; -import Severity from 'vs/base/common/severity'; -import { URI } from 'vs/base/common/uri'; -import { TextEditorCursorStyle } from 'vs/editor/common/config/editorOptions'; -import { OverviewRulerLane } from 'vs/editor/common/model'; -import * as languageConfiguration from 'vs/editor/common/modes/languageConfiguration'; -import { score } from 'vs/editor/common/modes/languageSelector'; -import * as files from 'vs/platform/files/common/files'; -import { ExtHostContext, IInitData, IMainContext, MainContext } from 'vs/workbench/api/common/extHost.protocol'; -import { ExtHostApiCommands } from 'vs/workbench/api/common/extHostApiCommands'; -import { ExtHostClipboard } from 'vs/workbench/api/common/extHostClipboard'; -import { ExtHostCommands } from 'vs/workbench/api/common/extHostCommands'; -import { ExtHostComments } from 'vs/workbench/api/common/extHostComments'; -import { ExtHostConfiguration, ExtHostConfigProvider } from 'vs/workbench/api/common/extHostConfiguration'; -// import { ExtHostDebugService } from 'vs/workbench/api/node/extHostDebugService'; -import { ExtHostDecorations } from 'vs/workbench/api/common/extHostDecorations'; -import { ExtHostDiagnostics } from 'vs/workbench/api/common/extHostDiagnostics'; -import { ExtHostDialogs } from 'vs/workbench/api/common/extHostDialogs'; -import { ExtHostDocumentContentProvider } from 'vs/workbench/api/common/extHostDocumentContentProviders'; -import { ExtHostDocumentSaveParticipant } from 'vs/workbench/api/common/extHostDocumentSaveParticipant'; -import { ExtHostDocuments } from 'vs/workbench/api/common/extHostDocuments'; -import { ExtHostDocumentsAndEditors } from 'vs/workbench/api/common/extHostDocumentsAndEditors'; -import { ExtensionActivatedByAPI } from 'vs/workbench/api/common/extHostExtensionActivator'; -import { ExtHostExtensionService } from './extHostExtensionService'; -import { ExtHostFileSystem } from 'vs/workbench/api/common/extHostFileSystem'; -import { ExtHostFileSystemEventService } from 'vs/workbench/api/common/extHostFileSystemEventService'; -import { ExtHostLanguageFeatures } from 'vs/workbench/api/common/extHostLanguageFeatures'; -import { ExtHostLanguages } from 'vs/workbench/api/common/extHostLanguages'; -import { ExtHostLogService } from 'vs/workbench/api/common/extHostLogService'; -import { ExtHostMessageService } from 'vs/workbench/api/common/extHostMessageService'; -import { ExtHostOutputService, PushOutputChannelFactory } from 'vs/workbench/api/common/extHostOutput'; -// import { LogOutputChannelFactory } from 'vs/workbench/api/node/extHostOutputService'; -import { ExtHostProgress } from 'vs/workbench/api/common/extHostProgress'; -import { ExtHostQuickOpen } from 'vs/workbench/api/common/extHostQuickOpen'; -import { ExtHostSCM } from 'vs/workbench/api/common/extHostSCM'; -// import { ExtHostSearch, registerEHSearchProviders } from 'vs/workbench/api/node/extHostSearch'; -import { ExtHostStatusBar } from 'vs/workbench/api/common/extHostStatusBar'; -import { ExtHostStorage } from 'vs/workbench/api/common/extHostStorage'; -// import { ExtHostTask } from 'vs/workbench/api/node/extHostTask'; -// import { ExtHostTerminalService } from 'vs/workbench/api/node/extHostTerminalService'; -import { ExtHostEditors } from 'vs/workbench/api/common/extHostTextEditors'; -import { ExtHostTreeViews } from 'vs/workbench/api/common/extHostTreeViews'; -// import { ExtHostDownloadService } from 'vs/workbench/api/node/extHostDownloadService'; -import * as typeConverters from 'vs/workbench/api/common/extHostTypeConverters'; -import * as extHostTypes from 'vs/workbench/api/common/extHostTypes'; -import { ExtHostUrls } from 'vs/workbench/api/common/extHostUrls'; -import { ExtHostWebviews } from 'vs/workbench/api/common/extHostWebview'; -import { ExtHostWindow } from 'vs/workbench/api/common/extHostWindow'; -import { ExtHostWorkspace } from 'vs/workbench/api/common/extHostWorkspace'; -import { throwProposedApiError, checkProposedApiEnabled } from 'vs/workbench/services/extensions/common/extensions'; -import { ProxyIdentifier } from 'vs/workbench/services/extensions/common/proxyIdentifier'; -import { ExtensionDescriptionRegistry } from 'vs/workbench/services/extensions/common/extensionDescriptionRegistry'; -import * as vscode from 'vscode'; -import { ExtensionIdentifier, IExtensionDescription } from 'vs/platform/extensions/common/extensions'; -import { originalFSPath } from 'vs/base/common/resources'; -// import { CLIServer } from 'vs/workbench/api/node/extHostCLIServer'; -import { values } from 'vs/base/common/collections'; -// import { Schemas } from 'vs/base/common/network'; -import { IURITransformer } from 'vs/base/common/uriIpc'; -import { ExtHostEditorInsets } from 'vs/workbench/api/common/extHostCodeInsets'; -import { ExtHostLabelService } from 'vs/workbench/api/common/extHostLabelService'; -// import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection'; -// import { InstantiationService } from 'vs/platform/instantiation/common/instantiationService'; -// import { getSingletonServiceDescriptors } from 'vs/platform/instantiation/common/extensions'; -import { getRemoteName } from 'vs/platform/remote/common/remoteHosts'; - -export interface IExtensionApiFactory { - (extension: IExtensionDescription, registry: ExtensionDescriptionRegistry, configProvider: ExtHostConfigProvider): typeof vscode; -} - -function proposedApiFunction(extension: IExtensionDescription, fn: T): T { - if (extension.enableProposedApi) { - return fn; - } else { - return throwProposedApiError.bind(null, extension) as any as T; - } -} - -/** - * This method instantiates and returns the extension API surface - */ -export function createApiFactory( - initData: IInitData, - rpcProtocol: IMainContext, - extHostWorkspace: ExtHostWorkspace, - extHostConfiguration: ExtHostConfiguration, - extensionService: ExtHostExtensionService, - extHostLogService: ExtHostLogService, - extHostStorage: ExtHostStorage, - uriTransformer: IURITransformer | null -): IExtensionApiFactory { - - // bootstrap services - // const services = new ServiceCollection(...getSingletonServiceDescriptors()); - // const instaService = new InstantiationService(services); - - // Addressable instances - rpcProtocol.set(ExtHostContext.ExtHostLogService, extHostLogService); - const extHostDecorations = rpcProtocol.set(ExtHostContext.ExtHostDecorations, new ExtHostDecorations(rpcProtocol)); - const extHostWebviews = rpcProtocol.set(ExtHostContext.ExtHostWebviews, new ExtHostWebviews(rpcProtocol, initData.environment)); - const extHostUrls = rpcProtocol.set(ExtHostContext.ExtHostUrls, new ExtHostUrls(rpcProtocol)); - const extHostDocumentsAndEditors = rpcProtocol.set(ExtHostContext.ExtHostDocumentsAndEditors, new ExtHostDocumentsAndEditors(rpcProtocol)); - const extHostDocuments = rpcProtocol.set(ExtHostContext.ExtHostDocuments, new ExtHostDocuments(rpcProtocol, extHostDocumentsAndEditors)); - const extHostDocumentContentProviders = rpcProtocol.set(ExtHostContext.ExtHostDocumentContentProviders, new ExtHostDocumentContentProvider(rpcProtocol, extHostDocumentsAndEditors, extHostLogService)); - const extHostDocumentSaveParticipant = rpcProtocol.set(ExtHostContext.ExtHostDocumentSaveParticipant, new ExtHostDocumentSaveParticipant(extHostLogService, extHostDocuments, rpcProtocol.getProxy(MainContext.MainThreadTextEditors))); - const extHostEditors = rpcProtocol.set(ExtHostContext.ExtHostEditors, new ExtHostEditors(rpcProtocol, extHostDocumentsAndEditors)); - const extHostCommands = rpcProtocol.set(ExtHostContext.ExtHostCommands, new ExtHostCommands(rpcProtocol, extHostLogService)); - const extHostTreeViews = rpcProtocol.set(ExtHostContext.ExtHostTreeViews, new ExtHostTreeViews(rpcProtocol.getProxy(MainContext.MainThreadTreeViews), extHostCommands, extHostLogService)); - // rpcProtocol.set(ExtHostContext.ExtHostDownloadService, new ExtHostDownloadService(rpcProtocol.getProxy(MainContext.MainThreadDownloadService), extHostCommands)); - rpcProtocol.set(ExtHostContext.ExtHostWorkspace, extHostWorkspace); - rpcProtocol.set(ExtHostContext.ExtHostConfiguration, extHostConfiguration); - const extHostEditorInsets = rpcProtocol.set(ExtHostContext.ExtHostEditorInsets, new ExtHostEditorInsets(rpcProtocol.getProxy(MainContext.MainThreadEditorInsets), extHostEditors, initData.environment)); - const extHostDiagnostics = rpcProtocol.set(ExtHostContext.ExtHostDiagnostics, new ExtHostDiagnostics(rpcProtocol)); - const extHostLanguageFeatures = rpcProtocol.set(ExtHostContext.ExtHostLanguageFeatures, new ExtHostLanguageFeatures(rpcProtocol, uriTransformer, extHostDocuments, extHostCommands, extHostDiagnostics, extHostLogService)); - const extHostFileSystem = rpcProtocol.set(ExtHostContext.ExtHostFileSystem, new ExtHostFileSystem(rpcProtocol, extHostLanguageFeatures)); - const extHostFileSystemEvent = rpcProtocol.set(ExtHostContext.ExtHostFileSystemEventService, new ExtHostFileSystemEventService(rpcProtocol, extHostDocumentsAndEditors)); - const extHostQuickOpen = rpcProtocol.set(ExtHostContext.ExtHostQuickOpen, new ExtHostQuickOpen(rpcProtocol, extHostWorkspace, extHostCommands)); - // const extHostTerminalService = rpcProtocol.set(ExtHostContext.ExtHostTerminalService, new ExtHostTerminalService(rpcProtocol, extHostConfiguration, extHostWorkspace, extHostDocumentsAndEditors, extHostLogService)); - // const extHostDebugService = rpcProtocol.set(ExtHostContext.ExtHostDebugService, instaService.createInstance(ExtHostDebugService, rpcProtocol, extHostWorkspace, extensionService, extHostDocumentsAndEditors, extHostConfiguration, extHostTerminalService, extHostCommands)); - const extHostSCM = rpcProtocol.set(ExtHostContext.ExtHostSCM, new ExtHostSCM(rpcProtocol, extHostCommands, extHostLogService)); - const extHostComment = rpcProtocol.set(ExtHostContext.ExtHostComments, new ExtHostComments(rpcProtocol, extHostCommands, extHostDocuments)); - // const extHostSearch = rpcProtocol.set(ExtHostContext.ExtHostSearch, new ExtHostSearch(rpcProtocol, uriTransformer, extHostLogService)); - // const extHostTask = rpcProtocol.set(ExtHostContext.ExtHostTask, new ExtHostTask(rpcProtocol, extHostWorkspace, extHostDocumentsAndEditors, extHostConfiguration, extHostTerminalService)); - const extHostWindow = rpcProtocol.set(ExtHostContext.ExtHostWindow, new ExtHostWindow(rpcProtocol)); - rpcProtocol.set(ExtHostContext.ExtHostExtensionService, extensionService); - const extHostProgress = rpcProtocol.set(ExtHostContext.ExtHostProgress, new ExtHostProgress(rpcProtocol.getProxy(MainContext.MainThreadProgress))); - const extHostOutputService = rpcProtocol.set(ExtHostContext.ExtHostOutputService, new ExtHostOutputService(PushOutputChannelFactory, initData.logsLocation, rpcProtocol)); - rpcProtocol.set(ExtHostContext.ExtHostStorage, extHostStorage); - const extHostLabelService = rpcProtocol.set(ExtHostContext.ExtHosLabelService, new ExtHostLabelService(rpcProtocol)); - - // if (initData.remote.isRemote && initData.remote.authority) { - // extHostTask.registerTaskSystem(Schemas.vscodeRemote, { - // scheme: Schemas.vscodeRemote, - // authority: initData.remote.authority, - // platform: process.platform - // }); - - // registerEHSearchProviders(extHostSearch, extHostLogService); - - // const cliServer = new CLIServer(extHostCommands); - // process.env['VSCODE_IPC_HOOK_CLI'] = cliServer.ipcHandlePath; - // } - - // todo@joh - const proxy: any = new Proxy({}, {}); - rpcProtocol.set(ExtHostContext.ExtHostTerminalService, proxy); - rpcProtocol.set(ExtHostContext.ExtHostDebugService, proxy); - rpcProtocol.set(ExtHostContext.ExtHostSearch, proxy); - rpcProtocol.set(ExtHostContext.ExtHostTask, proxy); - rpcProtocol.set(ExtHostContext.ExtHostDownloadService, proxy); - - // Check that no named customers are missing - const expected: ProxyIdentifier[] = values(ExtHostContext); - rpcProtocol.assertRegistered(expected); - - // Other instances - const extHostClipboard = new ExtHostClipboard(rpcProtocol); - const extHostMessageService = new ExtHostMessageService(rpcProtocol); - const extHostDialogs = new ExtHostDialogs(rpcProtocol); - const extHostStatusBar = new ExtHostStatusBar(rpcProtocol); - const extHostLanguages = new ExtHostLanguages(rpcProtocol, extHostDocuments); - - // Register an output channel for exthost log - const outputChannelName = initData.remote.isRemote ? nls.localize('remote extension host Log', "Remote Extension Host") : nls.localize('extension host Log', "Extension Host"); - extHostOutputService.createOutputChannelFromLogFile(outputChannelName, extHostLogService.logFile); - - // Register API-ish commands - ExtHostApiCommands.register(extHostCommands); - - return function (extension: IExtensionDescription, extensionRegistry: ExtensionDescriptionRegistry, configProvider: ExtHostConfigProvider): typeof vscode { - - // Check document selectors for being overly generic. Technically this isn't a problem but - // in practice many extensions say they support `fooLang` but need fs-access to do so. Those - // extension should specify then the `file`-scheme, e.g. `{ scheme: 'fooLang', language: 'fooLang' }` - // We only inform once, it is not a warning because we just want to raise awareness and because - // we cannot say if the extension is doing it right or wrong... - const checkSelector = (function () { - let done = (!extension.isUnderDevelopment); - function informOnce(selector: vscode.DocumentSelector) { - if (!done) { - console.info(`Extension '${extension.identifier.value}' uses a document selector without scheme. Learn more about this: https://go.microsoft.com/fwlink/?linkid=872305`); - done = true; - } - } - return function perform(selector: vscode.DocumentSelector): vscode.DocumentSelector { - if (Array.isArray(selector)) { - selector.forEach(perform); - } else if (typeof selector === 'string') { - informOnce(selector); - } else { - if (typeof selector.scheme === 'undefined') { - informOnce(selector); - } - if (!extension.enableProposedApi && typeof selector.exclusive === 'boolean') { - throwProposedApiError(extension); - } - } - return selector; - }; - })(); - - - // namespace: commands - const commands: typeof vscode.commands = { - registerCommand(id: string, command: (...args: any[]) => T | Thenable, thisArgs?: any): vscode.Disposable { - return extHostCommands.registerCommand(true, id, command, thisArgs); - }, - registerTextEditorCommand(id: string, callback: (textEditor: vscode.TextEditor, edit: vscode.TextEditorEdit, ...args: any[]) => void, thisArg?: any): vscode.Disposable { - return extHostCommands.registerCommand(true, id, (...args: any[]): any => { - const 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 occurred while running command ' + id, err); - }); - }); - }, - registerDiffInformationCommand: proposedApiFunction(extension, (id: string, callback: (diff: vscode.LineChange[], ...args: any[]) => any, thisArg?: any): vscode.Disposable => { - return extHostCommands.registerCommand(true, id, async (...args: any[]): Promise => { - const 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); - }, - onDidExecuteCommand: proposedApiFunction(extension, (listener, thisArgs?, disposables?) => { - checkProposedApiEnabled(extension); - return extHostCommands.onDidExecuteCommand(listener, thisArgs, disposables); - }), - }; - - // namespace: env - const env: typeof vscode.env = { - get machineId() { return initData.telemetryInfo.machineId; }, - get sessionId() { return initData.telemetryInfo.sessionId; }, - get language() { return initData.environment.appLanguage; }, - get appName() { return initData.environment.appName; }, - get appRoot() { return initData.environment.appRoot!.fsPath; }, - get uriScheme() { return initData.environment.appUriScheme; }, - get logLevel() { - checkProposedApiEnabled(extension); - return typeConverters.LogLevel.to(extHostLogService.getLevel()); - }, - get onDidChangeLogLevel() { - checkProposedApiEnabled(extension); - return Event.map(extHostLogService.onDidChangeLogLevel, l => typeConverters.LogLevel.to(l)); - }, - get clipboard(): vscode.Clipboard { - return extHostClipboard; - }, - get shell(): string { - throw new Error('not implemented'); - // return extHostTerminalService.getDefaultShell(configProvider); - }, - openExternal(uri: URI) { - return extHostWindow.openUri(uri, { allowTunneling: !!initData.remote.isRemote }); - }, - get remoteName() { - return getRemoteName(initData.remote.authority); - } - }; - if (!initData.environment.extensionTestsLocationURI) { - // allow to patch env-function when running tests - Object.freeze(env); - } - - const extensionKind = initData.remote.isRemote - ? extHostTypes.ExtensionKind.Workspace - : extHostTypes.ExtensionKind.UI; - - // namespace: extensions - const extensions: typeof vscode.extensions = { - getExtension(extensionId: string): Extension | undefined { - const desc = extensionRegistry.getExtensionDescription(extensionId); - if (desc) { - return new Extension(extensionService, desc, extensionKind); - } - return undefined; - }, - get all(): Extension[] { - return extensionRegistry.getAllExtensionDescriptions().map((desc) => new Extension(extensionService, desc, extensionKind)); - }, - get onDidChange() { - return extensionRegistry.onDidChange; - } - }; - - // namespace: languages - const languages: typeof vscode.languages = { - createDiagnosticCollection(name?: string): vscode.DiagnosticCollection { - return extHostDiagnostics.createDiagnosticCollection(name); - }, - get onDidChangeDiagnostics() { - return extHostDiagnostics.onDidChangeDiagnostics; - }, - getDiagnostics: (resource?: vscode.Uri) => { - return extHostDiagnostics.getDiagnostics(resource); - }, - getLanguages(): Thenable { - return extHostLanguages.getLanguages(); - }, - setTextDocumentLanguage(document: vscode.TextDocument, languageId: string): Thenable { - return extHostLanguages.changeLanguage(document.uri, languageId); - }, - match(selector: vscode.DocumentSelector, document: vscode.TextDocument): number { - return score(typeConverters.LanguageSelector.from(selector), document.uri, document.languageId, true); - }, - registerCodeActionsProvider(selector: vscode.DocumentSelector, provider: vscode.CodeActionProvider, metadata?: vscode.CodeActionProviderMetadata): vscode.Disposable { - return extHostLanguageFeatures.registerCodeActionProvider(extension, checkSelector(selector), provider, metadata); - }, - registerCodeLensProvider(selector: vscode.DocumentSelector, provider: vscode.CodeLensProvider): vscode.Disposable { - return extHostLanguageFeatures.registerCodeLensProvider(extension, checkSelector(selector), provider); - }, - registerDefinitionProvider(selector: vscode.DocumentSelector, provider: vscode.DefinitionProvider): vscode.Disposable { - return extHostLanguageFeatures.registerDefinitionProvider(extension, checkSelector(selector), provider); - }, - registerDeclarationProvider(selector: vscode.DocumentSelector, provider: vscode.DeclarationProvider): vscode.Disposable { - return extHostLanguageFeatures.registerDeclarationProvider(extension, checkSelector(selector), provider); - }, - registerImplementationProvider(selector: vscode.DocumentSelector, provider: vscode.ImplementationProvider): vscode.Disposable { - return extHostLanguageFeatures.registerImplementationProvider(extension, checkSelector(selector), provider); - }, - registerTypeDefinitionProvider(selector: vscode.DocumentSelector, provider: vscode.TypeDefinitionProvider): vscode.Disposable { - return extHostLanguageFeatures.registerTypeDefinitionProvider(extension, checkSelector(selector), provider); - }, - registerHoverProvider(selector: vscode.DocumentSelector, provider: vscode.HoverProvider): vscode.Disposable { - return extHostLanguageFeatures.registerHoverProvider(extension, checkSelector(selector), provider, extension.identifier); - }, - registerDocumentHighlightProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentHighlightProvider): vscode.Disposable { - return extHostLanguageFeatures.registerDocumentHighlightProvider(extension, checkSelector(selector), provider); - }, - registerReferenceProvider(selector: vscode.DocumentSelector, provider: vscode.ReferenceProvider): vscode.Disposable { - return extHostLanguageFeatures.registerReferenceProvider(extension, checkSelector(selector), provider); - }, - registerRenameProvider(selector: vscode.DocumentSelector, provider: vscode.RenameProvider): vscode.Disposable { - return extHostLanguageFeatures.registerRenameProvider(extension, checkSelector(selector), provider); - }, - registerDocumentSymbolProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentSymbolProvider, metadata?: vscode.DocumentSymbolProviderMetadata): vscode.Disposable { - return extHostLanguageFeatures.registerDocumentSymbolProvider(extension, checkSelector(selector), provider, metadata); - }, - registerWorkspaceSymbolProvider(provider: vscode.WorkspaceSymbolProvider): vscode.Disposable { - return extHostLanguageFeatures.registerWorkspaceSymbolProvider(extension, provider); - }, - registerDocumentFormattingEditProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentFormattingEditProvider): vscode.Disposable { - return extHostLanguageFeatures.registerDocumentFormattingEditProvider(extension, checkSelector(selector), provider); - }, - registerDocumentRangeFormattingEditProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentRangeFormattingEditProvider): vscode.Disposable { - return extHostLanguageFeatures.registerDocumentRangeFormattingEditProvider(extension, checkSelector(selector), provider); - }, - registerOnTypeFormattingEditProvider(selector: vscode.DocumentSelector, provider: vscode.OnTypeFormattingEditProvider, firstTriggerCharacter: string, ...moreTriggerCharacters: string[]): vscode.Disposable { - return extHostLanguageFeatures.registerOnTypeFormattingEditProvider(extension, checkSelector(selector), provider, [firstTriggerCharacter].concat(moreTriggerCharacters)); - }, - registerSignatureHelpProvider(selector: vscode.DocumentSelector, provider: vscode.SignatureHelpProvider, firstItem?: string | vscode.SignatureHelpProviderMetadata, ...remaining: string[]): vscode.Disposable { - if (typeof firstItem === 'object') { - return extHostLanguageFeatures.registerSignatureHelpProvider(extension, checkSelector(selector), provider, firstItem); - } - return extHostLanguageFeatures.registerSignatureHelpProvider(extension, checkSelector(selector), provider, typeof firstItem === 'undefined' ? [] : [firstItem, ...remaining]); - }, - registerCompletionItemProvider(selector: vscode.DocumentSelector, provider: vscode.CompletionItemProvider, ...triggerCharacters: string[]): vscode.Disposable { - return extHostLanguageFeatures.registerCompletionItemProvider(extension, checkSelector(selector), provider, triggerCharacters); - }, - registerDocumentLinkProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentLinkProvider): vscode.Disposable { - return extHostLanguageFeatures.registerDocumentLinkProvider(extension, checkSelector(selector), provider); - }, - registerColorProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentColorProvider): vscode.Disposable { - return extHostLanguageFeatures.registerColorProvider(extension, checkSelector(selector), provider); - }, - registerFoldingRangeProvider(selector: vscode.DocumentSelector, provider: vscode.FoldingRangeProvider): vscode.Disposable { - return extHostLanguageFeatures.registerFoldingRangeProvider(extension, checkSelector(selector), provider); - }, - registerSelectionRangeProvider(selector: vscode.DocumentSelector, provider: vscode.SelectionRangeProvider): vscode.Disposable { - return extHostLanguageFeatures.registerSelectionRangeProvider(extension, selector, provider); - }, - registerCallHierarchyProvider(selector: vscode.DocumentSelector, provider: vscode.CallHierarchyItemProvider): vscode.Disposable { - checkProposedApiEnabled(extension); - return extHostLanguageFeatures.registerCallHierarchyProvider(extension, selector, provider); - }, - setLanguageConfiguration: (language: string, configuration: vscode.LanguageConfiguration): vscode.Disposable => { - return extHostLanguageFeatures.setLanguageConfiguration(language, configuration); - } - }; - - // namespace: window - const window: typeof vscode.window = { - get activeTextEditor() { - return extHostEditors.getActiveTextEditor(); - }, - get visibleTextEditors() { - return extHostEditors.getVisibleTextEditors(); - }, - get activeTerminal(): vscode.Terminal { - throw new Error('not implemented'); - // return extHostTerminalService.activeTerminal; - }, - get terminals(): vscode.Terminal[] { - throw new Error('not implemented'); - // return extHostTerminalService.terminals; - }, - showTextDocument(documentOrUri: vscode.TextDocument | vscode.Uri, columnOrOptions?: vscode.ViewColumn | vscode.TextDocumentShowOptions, preserveFocus?: boolean): Thenable { - let documentPromise: Promise; - if (URI.isUri(documentOrUri)) { - documentPromise = Promise.resolve(workspace.openTextDocument(documentOrUri)); - } else { - documentPromise = Promise.resolve(documentOrUri); - } - return documentPromise.then(document => { - 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); - }, - onDidChangeTextEditorVisibleRanges(listener: (e: vscode.TextEditorVisibleRangesChangeEvent) => any, thisArgs?: any, disposables?: extHostTypes.Disposable[]) { - return extHostEditors.onDidChangeTextEditorVisibleRanges(listener, thisArgs, disposables); - }, - onDidChangeTextEditorViewColumn(listener, thisArg?, disposables?) { - return extHostEditors.onDidChangeTextEditorViewColumn(listener, thisArg, disposables); - }, - onDidCloseTerminal(listener, thisArg?, disposables?) { - throw new Error('not implemented'); - // return extHostTerminalService.onDidCloseTerminal(listener, thisArg, disposables); - }, - onDidOpenTerminal(listener, thisArg?, disposables?) { - throw new Error('not implemented'); - // return extHostTerminalService.onDidOpenTerminal(listener, thisArg, disposables); - }, - onDidChangeActiveTerminal(listener, thisArg?, disposables?) { - throw new Error('not implemented'); - // return extHostTerminalService.onDidChangeActiveTerminal(listener, thisArg, disposables); - }, - onDidChangeTerminalDimensions(listener, thisArg?, disposables?) { - throw new Error('not implemented'); - // return extHostTerminalService.onDidChangeTerminalDimensions(listener, thisArg, disposables); - }, - get state() { - return extHostWindow.state; - }, - onDidChangeWindowState(listener, thisArg?, disposables?) { - return extHostWindow.onDidChangeWindowState(listener, thisArg, disposables); - }, - showInformationMessage(message: string, first: vscode.MessageOptions | string | vscode.MessageItem, ...rest: Array) { - return extHostMessageService.showMessage(extension, Severity.Info, message, first, rest); - }, - showWarningMessage(message: string, first: vscode.MessageOptions | string | vscode.MessageItem, ...rest: Array) { - return extHostMessageService.showMessage(extension, Severity.Warning, message, first, rest); - }, - showErrorMessage(message: string, first: vscode.MessageOptions | string | vscode.MessageItem, ...rest: Array) { - return extHostMessageService.showMessage(extension, Severity.Error, message, first, rest); - }, - showQuickPick(items: any, options: vscode.QuickPickOptions, token?: vscode.CancellationToken): any { - return extHostQuickOpen.showQuickPick(items, !!extension.enableProposedApi, options, token); - }, - showWorkspaceFolderPick(options: vscode.WorkspaceFolderPickOptions) { - return extHostQuickOpen.showWorkspaceFolderPick(options); - }, - showInputBox(options?: vscode.InputBoxOptions, token?: vscode.CancellationToken) { - return extHostQuickOpen.showInput(options, token); - }, - showOpenDialog(options) { - return extHostDialogs.showOpenDialog(options); - }, - showSaveDialog(options) { - return extHostDialogs.showSaveDialog(options); - }, - createStatusBarItem(alignmentOrOptions?: vscode.StatusBarAlignment | vscode.window.StatusBarItemOptions, priority?: number): vscode.StatusBarItem { - let id: string; - let name: string; - let alignment: number | undefined; - - if (alignmentOrOptions && typeof alignmentOrOptions !== 'number') { - id = alignmentOrOptions.id; - name = alignmentOrOptions.name; - alignment = alignmentOrOptions.alignment; - priority = alignmentOrOptions.priority; - } else { - id = extension.identifier.value; - name = nls.localize('extensionLabel', "{0} (Extension)", extension.displayName || extension.name); - alignment = alignmentOrOptions; - priority = priority; - } - - return extHostStatusBar.createStatusBarEntry(id, name, alignment, 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 }, (progress, token) => task({ report(n: number) { /*noop*/ } })); - }, - withProgress(options: vscode.ProgressOptions, task: (progress: vscode.Progress<{ message?: string; worked?: number }>, token: vscode.CancellationToken) => Thenable) { - return extHostProgress.withProgress(extension, options, task); - }, - createOutputChannel(name: string): vscode.OutputChannel { - return extHostOutputService.createOutputChannel(name); - }, - createWebviewPanel(viewType: string, title: string, showOptions: vscode.ViewColumn | { viewColumn: vscode.ViewColumn, preserveFocus?: boolean }, options: vscode.WebviewPanelOptions & vscode.WebviewOptions): vscode.WebviewPanel { - return extHostWebviews.createWebviewPanel(extension, viewType, title, showOptions, options); - }, - createWebviewTextEditorInset(editor: vscode.TextEditor, line: number, height: number, options: vscode.WebviewOptions): vscode.WebviewEditorInset { - checkProposedApiEnabled(extension); - return extHostEditorInsets.createWebviewEditorInset(editor, line, height, options, extension); - }, - createTerminal(nameOrOptions?: vscode.TerminalOptions | vscode.ExtensionTerminalOptions | string, shellPath?: string, shellArgs?: string[] | string): vscode.Terminal { - throw new Error('not implemented'); - // if (typeof nameOrOptions === 'object') { - // if ('pty' in nameOrOptions) { - // return extHostTerminalService.createExtensionTerminal(nameOrOptions); - // } - // return extHostTerminalService.createTerminalFromOptions(nameOrOptions); - // } - // return extHostTerminalService.createTerminal(nameOrOptions, shellPath, shellArgs); - }, - createTerminalRenderer(name: string): vscode.TerminalRenderer { - throw new Error('not implemented'); - // return extHostTerminalService.createTerminalRenderer(name); - }, - registerTreeDataProvider(viewId: string, treeDataProvider: vscode.TreeDataProvider): vscode.Disposable { - return extHostTreeViews.registerTreeDataProvider(viewId, treeDataProvider, extension); - }, - createTreeView(viewId: string, options: { treeDataProvider: vscode.TreeDataProvider }): vscode.TreeView { - return extHostTreeViews.createTreeView(viewId, options, extension); - }, - registerWebviewPanelSerializer: (viewType: string, serializer: vscode.WebviewPanelSerializer) => { - return extHostWebviews.registerWebviewPanelSerializer(viewType, serializer); - }, - registerDecorationProvider: proposedApiFunction(extension, (provider: vscode.DecorationProvider) => { - return extHostDecorations.registerDecorationProvider(provider, extension.identifier); - }), - registerUriHandler(handler: vscode.UriHandler) { - return extHostUrls.registerUriHandler(extension.identifier, handler); - }, - createQuickPick(): vscode.QuickPick { - return extHostQuickOpen.createQuickPick(extension.identifier, !!extension.enableProposedApi); - }, - createInputBox(): vscode.InputBox { - return extHostQuickOpen.createInputBox(extension.identifier); - } - }; - - // namespace: workspace - const workspace: typeof vscode.workspace = { - get rootPath() { - return extHostWorkspace.getPath(); - }, - set rootPath(value) { - throw errors.readonly(); - }, - getWorkspaceFolder(resource) { - return extHostWorkspace.getWorkspaceFolder(resource); - }, - get workspaceFolders() { - return extHostWorkspace.getWorkspaceFolders(); - }, - get name() { - return extHostWorkspace.name; - }, - set name(value) { - throw errors.readonly(); - }, - get workspaceFile() { - return extHostWorkspace.workspaceFile; - }, - set workspaceFile(value) { - throw errors.readonly(); - }, - updateWorkspaceFolders: (index, deleteCount, ...workspaceFoldersToAdd) => { - return extHostWorkspace.updateWorkspaceFolders(extension, index, deleteCount || 0, ...workspaceFoldersToAdd); - }, - onDidChangeWorkspaceFolders: function (listener, thisArgs?, disposables?) { - return extHostWorkspace.onDidChangeWorkspace(listener, thisArgs, disposables); - }, - asRelativePath: (pathOrUri, includeWorkspace?) => { - return extHostWorkspace.getRelativePath(pathOrUri, includeWorkspace); - }, - findFiles: (include, exclude, maxResults?, token?) => { - // Note, undefined/null have different meanings on "exclude" - return extHostWorkspace.findFiles(typeConverters.GlobPattern.from(include), typeConverters.GlobPattern.from(exclude), maxResults, extension.identifier, token); - }, - findTextInFiles: (query: vscode.TextSearchQuery, optionsOrCallback: vscode.FindTextInFilesOptions | ((result: vscode.TextSearchResult) => void), callbackOrToken?: vscode.CancellationToken | ((result: vscode.TextSearchResult) => void), token?: vscode.CancellationToken) => { - let options: vscode.FindTextInFilesOptions; - let callback: (result: vscode.TextSearchResult) => void; - - if (typeof optionsOrCallback === 'object') { - options = optionsOrCallback; - callback = callbackOrToken as (result: vscode.TextSearchResult) => void; - } else { - options = {}; - callback = optionsOrCallback; - token = callbackOrToken as vscode.CancellationToken; - } - - return extHostWorkspace.findTextInFiles(query, options || {}, callback, extension.identifier, token); - }, - saveAll: (includeUntitled?) => { - return extHostWorkspace.saveAll(includeUntitled); - }, - applyEdit(edit: vscode.WorkspaceEdit): Thenable { - return extHostEditors.applyWorkspaceEdit(edit); - }, - createFileSystemWatcher: (pattern, ignoreCreate, ignoreChange, ignoreDelete): vscode.FileSystemWatcher => { - return extHostFileSystemEvent.createFileSystemWatcher(typeConverters.GlobPattern.from(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: Thenable; - - const options = uriOrFileNameOrOptions as { language?: string; content?: string; }; - if (typeof uriOrFileNameOrOptions === 'string') { - uriPromise = Promise.resolve(URI.file(uriOrFileNameOrOptions)); - } else if (uriOrFileNameOrOptions instanceof URI) { - uriPromise = Promise.resolve(uriOrFileNameOrOptions); - } else if (!options || typeof options === 'object') { - uriPromise = extHostDocuments.createDocumentData(options); - } else { - throw new Error('illegal argument - uriOrFileNameOrOptions'); - } - - return uriPromise.then(uri => { - return extHostDocuments.ensureDocumentData(uri).then(() => { - return extHostDocuments.getDocument(uri); - }); - }); - }, - 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.getOnWillSaveTextDocumentEvent(extension)(listener, thisArgs, disposables); - }, - onDidChangeConfiguration: (listener: (_: any) => any, thisArgs?: any, disposables?: extHostTypes.Disposable[]) => { - return configProvider.onDidChangeConfiguration(listener, thisArgs, disposables); - }, - getConfiguration(section?: string, resource?: vscode.Uri): vscode.WorkspaceConfiguration { - resource = arguments.length === 1 ? undefined : resource; - return configProvider.getConfiguration(section, resource, extension.identifier); - }, - registerTextDocumentContentProvider(scheme: string, provider: vscode.TextDocumentContentProvider) { - return extHostDocumentContentProviders.registerTextDocumentContentProvider(scheme, provider); - }, - registerTaskProvider: (type: string, provider: vscode.TaskProvider) => { - throw new Error('not implemented'); - // return extHostTask.registerTaskProvider(extension, type, provider); - }, - registerFileSystemProvider(scheme, provider, options) { - return extHostFileSystem.registerFileSystemProvider(scheme, provider, options); - }, - get fs() { - return extHostFileSystem.fileSystem; - }, - registerFileSearchProvider: proposedApiFunction(extension, (scheme: string, provider: vscode.FileSearchProvider) => { - throw new Error('not implemented'); - // return extHostSearch.registerFileSearchProvider(scheme, provider); - }), - registerTextSearchProvider: proposedApiFunction(extension, (scheme: string, provider: vscode.TextSearchProvider) => { - throw new Error('not implemented'); - // return extHostSearch.registerTextSearchProvider(scheme, provider); - }), - registerRemoteAuthorityResolver: proposedApiFunction(extension, (authorityPrefix: string, resolver: vscode.RemoteAuthorityResolver) => { - return extensionService.registerRemoteAuthorityResolver(authorityPrefix, resolver); - }), - registerResourceLabelFormatter: proposedApiFunction(extension, (formatter: vscode.ResourceLabelFormatter) => { - return extHostLabelService.$registerResourceLabelFormatter(formatter); - }), - onDidRenameFile: proposedApiFunction(extension, (listener: (e: vscode.FileRenameEvent) => any, thisArg?: any, disposables?: vscode.Disposable[]) => { - return extHostFileSystemEvent.onDidRenameFile(listener, thisArg, disposables); - }), - onWillRenameFile: proposedApiFunction(extension, (listener: (e: vscode.FileWillRenameEvent) => any, thisArg?: any, disposables?: vscode.Disposable[]) => { - return extHostFileSystemEvent.getOnWillRenameFileEvent(extension)(listener, thisArg, disposables); - }) - }; - - // namespace: scm - const scm: typeof vscode.scm = { - get inputBox() { - return extHostSCM.getLastInputBox(extension)!; // Strict null override - Deprecated api - }, - createSourceControl(id: string, label: string, rootUri?: vscode.Uri) { - return extHostSCM.createSourceControl(extension, id, label, rootUri); - } - }; - - const comment: typeof vscode.comments = { - createCommentController(id: string, label: string) { - return extHostComment.createCommentController(extension, id, label); - } - }; - - const comments = comment; - - // namespace: debug - // const debug: typeof vscode.debug = { - // get activeDebugSession() { - // return extHostDebugService.activeDebugSession; - // }, - // get activeDebugConsole() { - // return extHostDebugService.activeDebugConsole; - // }, - // get breakpoints() { - // return extHostDebugService.breakpoints; - // }, - // onDidStartDebugSession(listener, thisArg?, disposables?) { - // return extHostDebugService.onDidStartDebugSession(listener, thisArg, disposables); - // }, - // onDidTerminateDebugSession(listener, thisArg?, disposables?) { - // return extHostDebugService.onDidTerminateDebugSession(listener, thisArg, disposables); - // }, - // onDidChangeActiveDebugSession(listener, thisArg?, disposables?) { - // return extHostDebugService.onDidChangeActiveDebugSession(listener, thisArg, disposables); - // }, - // onDidReceiveDebugSessionCustomEvent(listener, thisArg?, disposables?) { - // return extHostDebugService.onDidReceiveDebugSessionCustomEvent(listener, thisArg, disposables); - // }, - // onDidChangeBreakpoints(listener, thisArgs?, disposables?) { - // return extHostDebugService.onDidChangeBreakpoints(listener, thisArgs, disposables); - // }, - // registerDebugConfigurationProvider(debugType: string, provider: vscode.DebugConfigurationProvider) { - // return extHostDebugService.registerDebugConfigurationProvider(debugType, provider); - // }, - // registerDebugAdapterDescriptorFactory(debugType: string, factory: vscode.DebugAdapterDescriptorFactory) { - // return extHostDebugService.registerDebugAdapterDescriptorFactory(extension, debugType, factory); - // }, - // registerDebugAdapterTrackerFactory(debugType: string, factory: vscode.DebugAdapterTrackerFactory) { - // return extHostDebugService.registerDebugAdapterTrackerFactory(debugType, factory); - // }, - // startDebugging(folder: vscode.WorkspaceFolder | undefined, nameOrConfig: string | vscode.DebugConfiguration, parentSession?: vscode.DebugSession) { - // return extHostDebugService.startDebugging(folder, nameOrConfig, parentSession); - // }, - // addBreakpoints(breakpoints: vscode.Breakpoint[]) { - // return extHostDebugService.addBreakpoints(breakpoints); - // }, - // removeBreakpoints(breakpoints: vscode.Breakpoint[]) { - // return extHostDebugService.removeBreakpoints(breakpoints); - // } - // }; - - // const tasks: typeof vscode.tasks = { - // registerTaskProvider: (type: string, provider: vscode.TaskProvider) => { - // return extHostTask.registerTaskProvider(extension, type, provider); - // }, - // fetchTasks: (filter?: vscode.TaskFilter): Thenable => { - // return extHostTask.fetchTasks(filter); - // }, - // executeTask: (task: vscode.Task): Thenable => { - // return extHostTask.executeTask(extension, task); - // }, - // get taskExecutions(): vscode.TaskExecution[] { - // return extHostTask.taskExecutions; - // }, - // onDidStartTask: (listeners, thisArgs?, disposables?) => { - // return extHostTask.onDidStartTask(listeners, thisArgs, disposables); - // }, - // onDidEndTask: (listeners, thisArgs?, disposables?) => { - // return extHostTask.onDidEndTask(listeners, thisArgs, disposables); - // }, - // onDidStartTaskProcess: (listeners, thisArgs?, disposables?) => { - // return extHostTask.onDidStartTaskProcess(listeners, thisArgs, disposables); - // }, - // onDidEndTaskProcess: (listeners, thisArgs?, disposables?) => { - // return extHostTask.onDidEndTaskProcess(listeners, thisArgs, disposables); - // } - // }; - - return { - version: initData.version, - // namespaces - commands, - get debug(): typeof vscode.debug { throw new Error('not implemented'); }, - env, - extensions, - languages, - scm, - comment, - comments, - get tasks(): typeof vscode.tasks { throw new Error('not implemented'); }, - window, - workspace, - // types - Breakpoint: extHostTypes.Breakpoint, - CancellationTokenSource: CancellationTokenSource, - CodeAction: extHostTypes.CodeAction, - CodeActionKind: extHostTypes.CodeActionKind, - CodeActionTrigger: extHostTypes.CodeActionTrigger, - CodeLens: extHostTypes.CodeLens, - CodeInset: extHostTypes.CodeInset, - Color: extHostTypes.Color, - ColorInformation: extHostTypes.ColorInformation, - ColorPresentation: extHostTypes.ColorPresentation, - CommentThreadCollapsibleState: extHostTypes.CommentThreadCollapsibleState, - CommentMode: extHostTypes.CommentMode, - CompletionItem: extHostTypes.CompletionItem, - CompletionItemKind: extHostTypes.CompletionItemKind, - CompletionList: extHostTypes.CompletionList, - CompletionTriggerKind: extHostTypes.CompletionTriggerKind, - ConfigurationTarget: extHostTypes.ConfigurationTarget, - DebugAdapterExecutable: extHostTypes.DebugAdapterExecutable, - DebugAdapterServer: extHostTypes.DebugAdapterServer, - DecorationRangeBehavior: extHostTypes.DecorationRangeBehavior, - Diagnostic: extHostTypes.Diagnostic, - DiagnosticRelatedInformation: extHostTypes.DiagnosticRelatedInformation, - DiagnosticSeverity: extHostTypes.DiagnosticSeverity, - DiagnosticTag: extHostTypes.DiagnosticTag, - Disposable: extHostTypes.Disposable, - DocumentHighlight: extHostTypes.DocumentHighlight, - DocumentHighlightKind: extHostTypes.DocumentHighlightKind, - DocumentLink: extHostTypes.DocumentLink, - DocumentSymbol: extHostTypes.DocumentSymbol, - EndOfLine: extHostTypes.EndOfLine, - EventEmitter: Emitter, - ExtensionExecutionContext: extHostTypes.ExtensionExecutionContext, - ExtensionKind: extHostTypes.ExtensionKind, - CustomExecution: extHostTypes.CustomExecution, - CustomExecution2: extHostTypes.CustomExecution2, - FileChangeType: extHostTypes.FileChangeType, - FileSystemError: extHostTypes.FileSystemError, - FileType: files.FileType, - FoldingRange: extHostTypes.FoldingRange, - FoldingRangeKind: extHostTypes.FoldingRangeKind, - FunctionBreakpoint: extHostTypes.FunctionBreakpoint, - Hover: extHostTypes.Hover, - IndentAction: languageConfiguration.IndentAction, - Location: extHostTypes.Location, - LogLevel: extHostTypes.LogLevel, - MarkdownString: extHostTypes.MarkdownString, - OverviewRulerLane: OverviewRulerLane, - ParameterInformation: extHostTypes.ParameterInformation, - Position: extHostTypes.Position, - ProcessExecution: extHostTypes.ProcessExecution, - ProgressLocation: extHostTypes.ProgressLocation, - QuickInputButtons: extHostTypes.QuickInputButtons, - Range: extHostTypes.Range, - RelativePattern: extHostTypes.RelativePattern, - ResolvedAuthority: extHostTypes.ResolvedAuthority, - RemoteAuthorityResolverError: extHostTypes.RemoteAuthorityResolverError, - Selection: extHostTypes.Selection, - SelectionRange: extHostTypes.SelectionRange, - ShellExecution: extHostTypes.ShellExecution, - ShellQuoting: extHostTypes.ShellQuoting, - SignatureHelpTriggerKind: extHostTypes.SignatureHelpTriggerKind, - SignatureHelp: extHostTypes.SignatureHelp, - SignatureInformation: extHostTypes.SignatureInformation, - SnippetString: extHostTypes.SnippetString, - SourceBreakpoint: extHostTypes.SourceBreakpoint, - SourceControlInputBoxValidationType: extHostTypes.SourceControlInputBoxValidationType, - StatusBarAlignment: extHostTypes.StatusBarAlignment, - SymbolInformation: extHostTypes.SymbolInformation, - SymbolKind: extHostTypes.SymbolKind, - Task: extHostTypes.Task, - Task2: extHostTypes.Task, - TaskGroup: extHostTypes.TaskGroup, - TaskPanelKind: extHostTypes.TaskPanelKind, - TaskRevealKind: extHostTypes.TaskRevealKind, - TaskScope: extHostTypes.TaskScope, - TextDocumentSaveReason: extHostTypes.TextDocumentSaveReason, - TextEdit: extHostTypes.TextEdit, - TextEditorCursorStyle: TextEditorCursorStyle, - TextEditorLineNumbersStyle: extHostTypes.TextEditorLineNumbersStyle, - TextEditorRevealType: extHostTypes.TextEditorRevealType, - TextEditorSelectionChangeKind: extHostTypes.TextEditorSelectionChangeKind, - ThemeColor: extHostTypes.ThemeColor, - ThemeIcon: extHostTypes.ThemeIcon, - TreeItem: extHostTypes.TreeItem, - TreeItem2: extHostTypes.TreeItem, - TreeItemCollapsibleState: extHostTypes.TreeItemCollapsibleState, - Uri: URI, - ViewColumn: extHostTypes.ViewColumn, - WorkspaceEdit: extHostTypes.WorkspaceEdit, - // proposed - CallHierarchyDirection: extHostTypes.CallHierarchyDirection, - CallHierarchyItem: extHostTypes.CallHierarchyItem - }; - }; -} - -class Extension implements vscode.Extension { - - private _extensionService: ExtHostExtensionService; - private _identifier: ExtensionIdentifier; - - readonly id: string; - readonly extensionPath: string; - readonly packageJSON: IExtensionDescription; - readonly extensionKind: vscode.ExtensionKind; - - constructor(extensionService: ExtHostExtensionService, description: IExtensionDescription, kind: extHostTypes.ExtensionKind) { - this._extensionService = extensionService; - this._identifier = description.identifier; - this.id = description.identifier.value; - this.extensionPath = path.normalize(originalFSPath(description.extensionLocation)); - this.packageJSON = description; - this.extensionKind = kind; - } - - get isActive(): boolean { - return this._extensionService.isActivated(this._identifier); - } - - get exports(): T { - if (this.packageJSON.api === 'none') { - return undefined!; // Strict nulloverride - Public api - } - return this._extensionService.getExtensionExports(this._identifier); - } - - activate(): Thenable { - return this._extensionService.activateByIdWithErrors(this._identifier, new ExtensionActivatedByAPI(false)).then(() => this.exports); - } -} diff --git a/src/vs/workbench/services/extensions/worker/extHost.services.ts b/src/vs/workbench/services/extensions/worker/extHost.services.ts new file mode 100644 index 00000000000..69ad6dbfe4b --- /dev/null +++ b/src/vs/workbench/services/extensions/worker/extHost.services.ts @@ -0,0 +1,51 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; +import { IExtHostOutputService, ExtHostOutputService } from 'vs/workbench/api/common/extHostOutput'; +import { IExtHostWorkspace, ExtHostWorkspace } from 'vs/workbench/api/common/extHostWorkspace'; +import { IExtHostDecorations, ExtHostDecorations } from 'vs/workbench/api/common/extHostDecorations'; +import { IExtHostConfiguration, ExtHostConfiguration } from 'vs/workbench/api/common/extHostConfiguration'; +import { IExtHostCommands, ExtHostCommands } from 'vs/workbench/api/common/extHostCommands'; +import { IExtHostDocumentsAndEditors, ExtHostDocumentsAndEditors } from 'vs/workbench/api/common/extHostDocumentsAndEditors'; +import { IExtHostTerminalService } from 'vs/workbench/api/common/extHostTerminalService'; +import { IExtHostTask } from 'vs/workbench/api/common/extHostTask'; +import { IExtHostDebugService } from 'vs/workbench/api/common/extHostDebugService'; +import { IExtHostSearch } from 'vs/workbench/api/common/extHostSearch'; +import { IExtensionStoragePaths } from 'vs/workbench/api/common/extHostStoragePaths'; +import { IExtHostExtensionService } from 'vs/workbench/api/common/extHostExtensionService'; +import { IExtHostStorage, ExtHostStorage } from 'vs/workbench/api/common/extHostStorage'; +import { ExtHostExtensionService } from 'vs/workbench/api/worker/extHostExtensionService'; +import { ServiceIdentifier } from 'vs/platform/instantiation/common/instantiation'; +import { ExtensionStoragePaths } from 'vs/workbench/api/worker/extHostStoragePaths'; + + +// register singleton services +registerSingleton(IExtHostOutputService, ExtHostOutputService); +registerSingleton(IExtHostWorkspace, ExtHostWorkspace); +registerSingleton(IExtHostDecorations, ExtHostDecorations); +registerSingleton(IExtHostConfiguration, ExtHostConfiguration); +registerSingleton(IExtHostCommands, ExtHostCommands); +registerSingleton(IExtHostDocumentsAndEditors, ExtHostDocumentsAndEditors); +registerSingleton(IExtHostStorage, ExtHostStorage); +registerSingleton(IExtensionStoragePaths, ExtensionStoragePaths); +registerSingleton(IExtHostExtensionService, ExtHostExtensionService); + +// register services that only throw errors +function NotImplementedProxy(name: ServiceIdentifier): { new(): T } { + return class { + constructor() { + return new Proxy({}, { + get(_target: any, prop: any) { + throw new Error(`Not Implemented: ${name}->${String(prop)}`); + } + }); + } + }; +} +registerSingleton(IExtHostTerminalService, class extends NotImplementedProxy(IExtHostTerminalService) { }); +registerSingleton(IExtHostTask, class extends NotImplementedProxy(IExtHostTask) { }); +registerSingleton(IExtHostDebugService, class extends NotImplementedProxy(IExtHostDebugService) { }); +registerSingleton(IExtHostSearch, class extends NotImplementedProxy(IExtHostSearch) { }); diff --git a/src/vs/workbench/services/extensions/worker/extHostExtensionService.ts b/src/vs/workbench/services/extensions/worker/extHostExtensionService.ts deleted file mode 100644 index 6e4cc7adb42..00000000000 --- a/src/vs/workbench/services/extensions/worker/extHostExtensionService.ts +++ /dev/null @@ -1,826 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import * as nls from 'vs/nls'; -import * as path from 'vs/base/common/path'; -import { originalFSPath } from 'vs/base/common/resources'; -import { Barrier } from 'vs/base/common/async'; -import { dispose, toDisposable, DisposableStore } from 'vs/base/common/lifecycle'; -import { TernarySearchTree } from 'vs/base/common/map'; -import { URI } from 'vs/base/common/uri'; -import { ILogService } from 'vs/platform/log/common/log'; -import { createApiFactory, IExtensionApiFactory } from './extHost.api.impl'; -// import { NodeModuleRequireInterceptor, VSCodeNodeModuleFactory, KeytarNodeModuleFactory, OpenNodeModuleFactory } from 'vs/workbench/api/node/extHostRequireInterceptor'; -import { ExtHostExtensionServiceShape, IEnvironment, IInitData, IMainContext, MainContext, MainThreadExtensionServiceShape, MainThreadTelemetryShape, MainThreadWorkspaceShape, IResolveAuthorityResult } from 'vs/workbench/api/common/extHost.protocol'; -import { ExtHostConfiguration } from 'vs/workbench/api/common/extHostConfiguration'; -import { ActivatedExtension, EmptyExtension, ExtensionActivatedByAPI, ExtensionActivatedByEvent, ExtensionActivationReason, ExtensionActivationTimes, ExtensionActivationTimesBuilder, ExtensionsActivator, IExtensionAPI, IExtensionContext, IExtensionModule, HostExtension, ExtensionActivationTimesFragment } from 'vs/workbench/api/common/extHostExtensionActivator'; -import { ExtHostLogService } from 'vs/workbench/api/common/extHostLogService'; -import { ExtHostStorage } from 'vs/workbench/api/common/extHostStorage'; -import { ExtHostWorkspace } from 'vs/workbench/api/common/extHostWorkspace'; -import { ExtensionActivationError, nullExtensionDescription } from 'vs/workbench/services/extensions/common/extensions'; -import { ExtensionDescriptionRegistry } from 'vs/workbench/services/extensions/common/extensionDescriptionRegistry'; -// import { connectProxyResolver } from 'vs/workbench/services/extensions/node/proxyResolver'; -import { CancellationTokenSource } from 'vs/base/common/cancellation'; -import * as errors from 'vs/base/common/errors'; -import * as vscode from 'vscode'; -import { ExtensionIdentifier, IExtensionDescription } from 'vs/platform/extensions/common/extensions'; -import { Schemas } from 'vs/base/common/network'; -// import { withNullAsUndefined } from 'vs/base/common/types'; -import { VSBuffer } from 'vs/base/common/buffer'; -import { ExtensionMemento } from 'vs/workbench/api/common/extHostMemento'; -// import { ExtensionStoragePaths } from 'vs/workbench/api/node/extHostStoragePaths'; -import { RemoteAuthorityResolverError, ExtensionExecutionContext } from 'vs/workbench/api/common/extHostTypes'; -import { IURITransformer } from 'vs/base/common/uriIpc'; -import { ResolvedAuthority, ResolvedOptions } from 'vs/platform/remote/common/remoteAuthorityResolver'; -import { endsWith } from 'vs/base/common/strings'; - -interface ITestRunner { - /** Old test runner API, as exported from `vscode/lib/testrunner` */ - run(testsRoot: string, clb: (error: Error, failures?: number) => void): void; -} - -interface INewTestRunner { - /** New test runner API, as explained in the extension test doc */ - run(): Promise; -} - -export interface IHostUtils { - exit(code?: number): void; - exists(path: string): Promise; - realpath(path: string): Promise; -} - -type TelemetryActivationEventFragment = { - id: { classification: 'PublicNonPersonalData', purpose: 'FeatureInsight' }; - name: { classification: 'PublicNonPersonalData', purpose: 'FeatureInsight' }; - extensionVersion: { classification: 'PublicNonPersonalData', purpose: 'FeatureInsight' }; - publisherDisplayName: { classification: 'SystemMetaData', purpose: 'FeatureInsight' }; - activationEvents: { classification: 'SystemMetaData', purpose: 'FeatureInsight' }; - isBuiltin: { classification: 'SystemMetaData', purpose: 'FeatureInsight', isMeasurement: true }; - reason: { classification: 'SystemMetaData', purpose: 'FeatureInsight' }; -}; - -export class ExtHostExtensionService implements ExtHostExtensionServiceShape { - - private static readonly WORKSPACE_CONTAINS_TIMEOUT = 7000; - - private readonly _hostUtils: IHostUtils; - private readonly _initData: IInitData; - private readonly _extHostContext: IMainContext; - private readonly _extHostWorkspace: ExtHostWorkspace; - private readonly _extHostConfiguration: ExtHostConfiguration; - // private readonly _environment: IEnvironment; - private readonly _extHostLogService: ExtHostLogService; - - private readonly _mainThreadWorkspaceProxy: MainThreadWorkspaceShape; - private readonly _mainThreadTelemetryProxy: MainThreadTelemetryShape; - private readonly _mainThreadExtensionsProxy: MainThreadExtensionServiceShape; - - private readonly _almostReadyToRunExtensions: Barrier; - private readonly _readyToStartExtensionHost: Barrier; - private readonly _readyToRunExtensions: Barrier; - private readonly _registry: ExtensionDescriptionRegistry; - private readonly _storage: ExtHostStorage; - // private readonly _storagePath: ExtensionStoragePaths; - private readonly _activator: ExtensionsActivator; - private _extensionPathIndex: Promise> | null; - private readonly _extensionApiFactory: IExtensionApiFactory; - - private readonly _resolvers: { [authorityPrefix: string]: vscode.RemoteAuthorityResolver; }; - - private _started: boolean; - - private readonly _disposables: DisposableStore; - - constructor( - hostUtils: IHostUtils, - initData: IInitData, - extHostContext: IMainContext, - extHostWorkspace: ExtHostWorkspace, - extHostConfiguration: ExtHostConfiguration, - environment: IEnvironment, - extHostLogService: ExtHostLogService, - uriTransformer: IURITransformer | null - ) { - this._hostUtils = hostUtils; - this._initData = initData; - this._extHostContext = extHostContext; - this._extHostWorkspace = extHostWorkspace; - this._extHostConfiguration = extHostConfiguration; - // this._environment = environment; - this._extHostLogService = extHostLogService; - this._disposables = new DisposableStore(); - - this._mainThreadWorkspaceProxy = this._extHostContext.getProxy(MainContext.MainThreadWorkspace); - this._mainThreadTelemetryProxy = this._extHostContext.getProxy(MainContext.MainThreadTelemetry); - this._mainThreadExtensionsProxy = this._extHostContext.getProxy(MainContext.MainThreadExtensionService); - - this._almostReadyToRunExtensions = new Barrier(); - this._readyToStartExtensionHost = new Barrier(); - this._readyToRunExtensions = new Barrier(); - this._registry = new ExtensionDescriptionRegistry(initData.extensions); - this._storage = new ExtHostStorage(this._extHostContext); - // this._storagePath = new ExtensionStoragePaths(withNullAsUndefined(initData.workspace), initData.environment); - - const hostExtensions = new Set(); - initData.hostExtensions.forEach((extensionId) => hostExtensions.add(ExtensionIdentifier.toKey(extensionId))); - - this._activator = new ExtensionsActivator(this._registry, initData.resolvedExtensions, initData.hostExtensions, { - onExtensionActivationError: (extensionId: ExtensionIdentifier, error: ExtensionActivationError): void => { - this._mainThreadExtensionsProxy.$onExtensionActivationError(extensionId, error); - }, - - actualActivateExtension: async (extensionId: ExtensionIdentifier, reason: ExtensionActivationReason): Promise => { - if (hostExtensions.has(ExtensionIdentifier.toKey(extensionId))) { - const activationEvent = (reason instanceof ExtensionActivatedByEvent ? reason.activationEvent : null); - await this._mainThreadExtensionsProxy.$activateExtension(extensionId, activationEvent); - return new HostExtension(); - } - const extensionDescription = this._registry.getExtensionDescription(extensionId)!; - return this._activateExtension(extensionDescription, reason); - } - }); - this._extensionPathIndex = null; - - // initialize API first (i.e. do not release barrier until the API is initialized) - this._extensionApiFactory = createApiFactory( - this._initData, - this._extHostContext, - this._extHostWorkspace, - this._extHostConfiguration, - this, - this._extHostLogService, - this._storage, - uriTransformer - ); - - this._resolvers = Object.create(null); - - this._started = false; - - this._initialize(); - - if (this._initData.autoStart) { - this._startExtensionHost(); - } - } - - private async _initialize(): Promise { - - // WORKER: globally define the vscode module and share that for all extensions - define('vscode', this._extensionApiFactory(nullExtensionDescription, this._registry, await this._extHostConfiguration.getConfigProvider())); - - try { - // const configProvider = await this._extHostConfiguration.getConfigProvider(); - // const extensionPaths = await this.getExtensionPathIndex(); - // NodeModuleRequireInterceptor.INSTANCE.register(new VSCodeNodeModuleFactory(this._extensionApiFactory, extensionPaths, this._registry, configProvider)); - // NodeModuleRequireInterceptor.INSTANCE.register(new KeytarNodeModuleFactory(this._extHostContext.getProxy(MainContext.MainThreadKeytar), this._environment)); - // if (this._initData.remoteAuthority) { - // NodeModuleRequireInterceptor.INSTANCE.register(new OpenNodeModuleFactory( - // this._extHostContext.getProxy(MainContext.MainThreadWindow), - // this._extHostContext.getProxy(MainContext.MainThreadTelemetry), - // extensionPaths - // )); - // } - - // // Do this when extension service exists, but extensions are not being activated yet. - // await connectProxyResolver(this._extHostWorkspace, configProvider, this, this._extHostLogService, this._mainThreadTelemetryProxy); - this._almostReadyToRunExtensions.open(); - - await this._extHostWorkspace.waitForInitializeCall(); - this._readyToStartExtensionHost.open(); - } catch (err) { - errors.onUnexpectedError(err); - } - } - - public async deactivateAll(): Promise { - let allPromises: Promise[] = []; - try { - const allExtensions = this._registry.getAllExtensionDescriptions(); - const allExtensionsIds = allExtensions.map(ext => ext.identifier); - const activatedExtensions = allExtensionsIds.filter(id => this.isActivated(id)); - - allPromises = activatedExtensions.map((extensionId) => { - return this._deactivate(extensionId); - }); - } catch (err) { - // TODO: write to log once we have one - } - await allPromises; - } - - public isActivated(extensionId: ExtensionIdentifier): boolean { - if (this._readyToRunExtensions.isOpen()) { - return this._activator.isActivated(extensionId); - } - return false; - } - - private _activateByEvent(activationEvent: string, startup: boolean): Promise { - const reason = new ExtensionActivatedByEvent(startup, activationEvent); - return this._activator.activateByEvent(activationEvent, reason); - } - - private _activateById(extensionId: ExtensionIdentifier, reason: ExtensionActivationReason): Promise { - return this._activator.activateById(extensionId, reason); - } - - public activateByIdWithErrors(extensionId: ExtensionIdentifier, reason: ExtensionActivationReason): Promise { - return this._activateById(extensionId, reason).then(() => { - const extension = this._activator.getActivatedExtension(extensionId); - if (extension.activationFailed) { - // activation failed => bubble up the error as the promise result - return Promise.reject(extension.activationFailedError); - } - return undefined; - }); - } - - public getExtensionRegistry(): Promise { - return this._readyToRunExtensions.wait().then(_ => this._registry); - } - - public getExtensionExports(extensionId: ExtensionIdentifier): IExtensionAPI | null | undefined { - if (this._readyToRunExtensions.isOpen()) { - return this._activator.getActivatedExtension(extensionId).exports; - } else { - return null; - } - } - - // create trie to enable fast 'filename -> extension id' look up - public getExtensionPathIndex(): Promise> { - if (!this._extensionPathIndex) { - const tree = TernarySearchTree.forPaths(); - const extensions = this._registry.getAllExtensionDescriptions().map(ext => { - if (!ext.main) { - return undefined; - } - return this._hostUtils.realpath(ext.extensionLocation.fsPath).then(value => tree.set(URI.file(value).fsPath, ext)); - }); - this._extensionPathIndex = Promise.all(extensions).then(() => tree); - } - return this._extensionPathIndex; - } - - private _deactivate(extensionId: ExtensionIdentifier): Promise { - let result = Promise.resolve(undefined); - - if (!this._readyToRunExtensions.isOpen()) { - return result; - } - - if (!this._activator.isActivated(extensionId)) { - return result; - } - - const extension = this._activator.getActivatedExtension(extensionId); - if (!extension) { - return result; - } - - // call deactivate if available - try { - if (typeof extension.module.deactivate === 'function') { - result = Promise.resolve(extension.module.deactivate()).then(undefined, (err) => { - // TODO: Do something with err if this is not the shutdown case - return Promise.resolve(undefined); - }); - } - } catch (err) { - // TODO: Do something with err if this is not the shutdown case - } - - // clean up subscriptions - try { - dispose(extension.subscriptions); - } catch (err) { - // TODO: Do something with err if this is not the shutdown case - } - - return result; - } - - // --- impl - - private _activateExtension(extensionDescription: IExtensionDescription, reason: ExtensionActivationReason): Promise { - this._mainThreadExtensionsProxy.$onWillActivateExtension(extensionDescription.identifier); - return this._doActivateExtension(extensionDescription, reason).then((activatedExtension) => { - const activationTimes = activatedExtension.activationTimes; - const activationEvent = (reason instanceof ExtensionActivatedByEvent ? reason.activationEvent : null); - this._mainThreadExtensionsProxy.$onDidActivateExtension(extensionDescription.identifier, activationTimes.startup, activationTimes.codeLoadingTime, activationTimes.activateCallTime, activationTimes.activateResolvedTime, activationEvent); - this._logExtensionActivationTimes(extensionDescription, reason, 'success', activationTimes); - return activatedExtension; - }, (err) => { - this._logExtensionActivationTimes(extensionDescription, reason, 'failure'); - throw err; - }); - } - - private _logExtensionActivationTimes(extensionDescription: IExtensionDescription, reason: ExtensionActivationReason, outcome: string, activationTimes?: ExtensionActivationTimes) { - const event = getTelemetryActivationEvent(extensionDescription, reason); - type ExtensionActivationTimesClassification = { - outcome: { classification: 'SystemMetaData', purpose: 'FeatureInsight' }; - } & TelemetryActivationEventFragment & ExtensionActivationTimesFragment; - - type ExtensionActivationTimesEvent = { - outcome: string - } & ActivationTimesEvent & TelemetryActivationEvent; - - type ActivationTimesEvent = { - startup?: boolean; - codeLoadingTime?: number; - activateCallTime?: number; - activateResolvedTime?: number; - }; - - this._mainThreadTelemetryProxy.$publicLog2('extensionActivationTimes', { - ...event, - ...(activationTimes || {}), - outcome - }); - } - - private _doActivateExtension(extensionDescription: IExtensionDescription, reason: ExtensionActivationReason): Promise { - const event = getTelemetryActivationEvent(extensionDescription, reason); - type ActivatePluginClassification = {} & TelemetryActivationEventFragment; - this._mainThreadTelemetryProxy.$publicLog2('activatePlugin', event); - if (!extensionDescription.main) { - // Treat the extension as being empty => NOT AN ERROR CASE - return Promise.resolve(new EmptyExtension(ExtensionActivationTimes.NONE)); - } - - this._extHostLogService.info(`ExtensionService#_doActivateExtension ${extensionDescription.identifier.value} ${JSON.stringify(reason)}`); - - const activationTimesBuilder = new ExtensionActivationTimesBuilder(reason.startup); - return Promise.all([ - loadCommonJSModule(this._extHostLogService, extensionDescription.main, activationTimesBuilder), - this._loadExtensionContext(extensionDescription) - ]).then(values => { - return ExtHostExtensionService._callActivate(this._extHostLogService, extensionDescription.identifier, values[0], values[1], activationTimesBuilder); - }); - } - - private _loadExtensionContext(extensionDescription: IExtensionDescription): Promise { - - const globalState = new ExtensionMemento(extensionDescription.identifier.value, true, this._storage); - const workspaceState = new ExtensionMemento(extensionDescription.identifier.value, false, this._storage); - - this._extHostLogService.trace(`ExtensionService#loadExtensionContext ${extensionDescription.identifier.value}`); - return Promise.all([ - globalState.whenReady, - workspaceState.whenReady, - // this._storagePath.whenReady - ]).then(() => { - const that = this; - return Object.freeze({ - globalState, - workspaceState, - subscriptions: [], - get extensionPath() { return extensionDescription.extensionLocation.fsPath; }, - // storagePath: this._storagePath.workspaceValue(extensionDescription), - // globalStoragePath: this._storagePath.globalValue(extensionDescription), - get storagePath(): string { throw new Error('not impl'); },// this._storagePath.workspaceValue(extensionDescription), - get globalStoragePath(): string { throw new Error('not impl'); },// this._storagePath.globalValue(extensionDescription), - asAbsolutePath: (relativePath: string) => { return path.join(extensionDescription.extensionLocation.fsPath, relativePath); }, - logPath: that._extHostLogService.getLogDirectory(extensionDescription.identifier), - executionContext: this._initData.remote.isRemote ? ExtensionExecutionContext.Remote : ExtensionExecutionContext.Local, - }); - }); - } - - private static _callActivate(logService: ILogService, extensionId: ExtensionIdentifier, extensionModule: IExtensionModule, context: IExtensionContext, activationTimesBuilder: ExtensionActivationTimesBuilder): Promise { - // Make sure the extension's surface is not undefined - extensionModule = extensionModule || { - activate: undefined, - deactivate: undefined - }; - - return this._callActivateOptional(logService, extensionId, extensionModule, context, activationTimesBuilder).then((extensionExports) => { - return new ActivatedExtension(false, null, activationTimesBuilder.build(), extensionModule, extensionExports, context.subscriptions); - }); - } - - private static _callActivateOptional(logService: ILogService, extensionId: ExtensionIdentifier, extensionModule: IExtensionModule, context: IExtensionContext, activationTimesBuilder: ExtensionActivationTimesBuilder): Promise { - if (typeof extensionModule.activate === 'function') { - try { - activationTimesBuilder.activateCallStart(); - logService.trace(`ExtensionService#_callActivateOptional ${extensionId.value}`); - // const activateResult: Promise = extensionModule.activate.apply(global, [context]); - const activateResult: Promise = extensionModule.activate.apply(undefined, [context]); - activationTimesBuilder.activateCallStop(); - - activationTimesBuilder.activateResolveStart(); - return Promise.resolve(activateResult).then((value) => { - activationTimesBuilder.activateResolveStop(); - return value; - }); - } catch (err) { - return Promise.reject(err); - } - } else { - // No activate found => the module is the extension's exports - return Promise.resolve(extensionModule); - } - } - - // -- eager activation - - // Handle "eager" activation extensions - private _handleEagerExtensions(): Promise { - this._activateByEvent('*', true).then(undefined, (err) => { - console.error(err); - }); - - this._disposables.add(this._extHostWorkspace.onDidChangeWorkspace((e) => this._handleWorkspaceContainsEagerExtensions(e.added))); - const folders = this._extHostWorkspace.workspace ? this._extHostWorkspace.workspace.folders : []; - return this._handleWorkspaceContainsEagerExtensions(folders); - } - - private _handleWorkspaceContainsEagerExtensions(folders: ReadonlyArray): Promise { - if (folders.length === 0) { - return Promise.resolve(undefined); - } - - return Promise.all( - this._registry.getAllExtensionDescriptions().map((desc) => { - return this._handleWorkspaceContainsEagerExtension(folders, desc); - }) - ).then(() => { }); - } - - private _handleWorkspaceContainsEagerExtension(folders: ReadonlyArray, desc: IExtensionDescription): Promise { - const activationEvents = desc.activationEvents; - if (!activationEvents) { - return Promise.resolve(undefined); - } - - if (this.isActivated(desc.identifier)) { - return Promise.resolve(undefined); - } - - const fileNames: string[] = []; - const globPatterns: string[] = []; - - for (const activationEvent of activationEvents) { - if (/^workspaceContains:/.test(activationEvent)) { - const fileNameOrGlob = activationEvent.substr('workspaceContains:'.length); - if (fileNameOrGlob.indexOf('*') >= 0 || fileNameOrGlob.indexOf('?') >= 0) { - globPatterns.push(fileNameOrGlob); - } else { - fileNames.push(fileNameOrGlob); - } - } - } - - if (fileNames.length === 0 && globPatterns.length === 0) { - return Promise.resolve(undefined); - } - - const fileNamePromise = Promise.all(fileNames.map((fileName) => this._activateIfFileName(folders, desc.identifier, fileName))).then(() => { }); - const globPatternPromise = this._activateIfGlobPatterns(folders, desc.identifier, globPatterns); - - return Promise.all([fileNamePromise, globPatternPromise]).then(() => { }); - } - - private async _activateIfFileName(folders: ReadonlyArray, extensionId: ExtensionIdentifier, fileName: string): Promise { - - // find exact path - for (const { uri } of folders) { - if (await this._hostUtils.exists(path.join(URI.revive(uri).fsPath, fileName))) { - // the file was found - return ( - this._activateById(extensionId, new ExtensionActivatedByEvent(true, `workspaceContains:${fileName}`)) - .then(undefined, err => console.error(err)) - ); - } - } - - return undefined; - } - - private async _activateIfGlobPatterns(folders: ReadonlyArray, extensionId: ExtensionIdentifier, globPatterns: string[]): Promise { - this._extHostLogService.trace(`extensionHostMain#activateIfGlobPatterns: fileSearch, extension: ${extensionId.value}, entryPoint: workspaceContains`); - - if (globPatterns.length === 0) { - return Promise.resolve(undefined); - } - - const tokenSource = new CancellationTokenSource(); - const searchP = this._mainThreadWorkspaceProxy.$checkExists(folders.map(folder => folder.uri), globPatterns, tokenSource.token); - - const timer = setTimeout(async () => { - tokenSource.cancel(); - this._activateById(extensionId, new ExtensionActivatedByEvent(true, `workspaceContainsTimeout:${globPatterns.join(',')}`)) - .then(undefined, err => console.error(err)); - }, ExtHostExtensionService.WORKSPACE_CONTAINS_TIMEOUT); - - let exists: boolean = false; - try { - exists = await searchP; - } catch (err) { - if (!errors.isPromiseCanceledError(err)) { - console.error(err); - } - } - - tokenSource.dispose(); - clearTimeout(timer); - - if (exists) { - // a file was found matching one of the glob patterns - return ( - this._activateById(extensionId, new ExtensionActivatedByEvent(true, `workspaceContains:${globPatterns.join(',')}`)) - .then(undefined, err => console.error(err)) - ); - } - - return Promise.resolve(undefined); - } - - private _handleExtensionTests(): Promise { - return this._doHandleExtensionTests().then(undefined, error => { - console.error(error); // ensure any error message makes it onto the console - - return Promise.reject(error); - }); - } - - private _doHandleExtensionTests(): Promise { - const { extensionDevelopmentLocationURI: extensionDevelopmentLocationURI, extensionTestsLocationURI } = this._initData.environment; - if (!(extensionDevelopmentLocationURI && extensionTestsLocationURI && extensionTestsLocationURI.scheme === Schemas.file)) { - return Promise.resolve(undefined); - } - - const extensionTestsPath = originalFSPath(extensionTestsLocationURI); - - // Require the test runner via node require from the provided path - let testRunner: ITestRunner | INewTestRunner | undefined; - let requireError: Error | undefined; - try { - testRunner = require.__$__nodeRequire(extensionTestsPath); - } catch (error) { - requireError = error; - } - - // Execute the runner if it follows the old `run` spec - if (testRunner && typeof testRunner.run === 'function') { - return new Promise((c, e) => { - const oldTestRunnerCallback = (error: Error, failures: number | undefined) => { - if (error) { - e(error.toString()); - } else { - c(undefined); - } - - // after tests have run, we shutdown the host - this._gracefulExit(error || (typeof failures === 'number' && failures > 0) ? 1 /* ERROR */ : 0 /* OK */); - }; - - const runResult = testRunner!.run(extensionTestsPath, oldTestRunnerCallback); - - // Using the new API `run(): Promise` - if (runResult && runResult.then) { - runResult - .then(() => { - c(); - this._gracefulExit(0); - }) - .catch((err: Error) => { - e(err.toString()); - this._gracefulExit(1); - }); - } - }); - } - - // Otherwise make sure to shutdown anyway even in case of an error - else { - this._gracefulExit(1 /* ERROR */); - } - - return Promise.reject(new Error(requireError ? requireError.toString() : nls.localize('extensionTestError', "Path {0} does not point to a valid extension test runner.", extensionTestsPath))); - } - - private _gracefulExit(code: number): void { - // to give the PH process a chance to flush any outstanding console - // messages to the main process, we delay the exit() by some time - setTimeout(() => { - // If extension tests are running, give the exit code to the renderer - if (this._initData.remote.isRemote && !!this._initData.environment.extensionTestsLocationURI) { - this._mainThreadExtensionsProxy.$onExtensionHostExit(code); - return; - } - - this._hostUtils.exit(code); - }, 500); - } - - private _startExtensionHost(): Promise { - if (this._started) { - throw new Error(`Extension host is already started!`); - } - this._started = true; - - return this._readyToStartExtensionHost.wait() - .then(() => this._readyToRunExtensions.open()) - .then(() => this._handleEagerExtensions()) - .then(() => this._handleExtensionTests()) - .then(() => { - this._extHostLogService.info(`eager extensions activated`); - }); - } - - // -- called by extensions - - public registerRemoteAuthorityResolver(authorityPrefix: string, resolver: vscode.RemoteAuthorityResolver): vscode.Disposable { - this._resolvers[authorityPrefix] = resolver; - return toDisposable(() => { - delete this._resolvers[authorityPrefix]; - }); - } - - // -- called by main thread - - public async $resolveAuthority(remoteAuthority: string, resolveAttempt: number): Promise { - const authorityPlusIndex = remoteAuthority.indexOf('+'); - if (authorityPlusIndex === -1) { - throw new Error(`Not an authority that can be resolved!`); - } - const authorityPrefix = remoteAuthority.substr(0, authorityPlusIndex); - - await this._almostReadyToRunExtensions.wait(); - await this._activateByEvent(`onResolveRemoteAuthority:${authorityPrefix}`, false); - - const resolver = this._resolvers[authorityPrefix]; - if (!resolver) { - throw new Error(`No remote extension installed to resolve ${authorityPrefix}.`); - } - - try { - const result = await resolver.resolve(remoteAuthority, { resolveAttempt }); - - // Split merged API result into separate authority/options - const authority: ResolvedAuthority = { - authority: remoteAuthority, - host: result.host, - port: result.port - }; - const options: ResolvedOptions = { - extensionHostEnv: result.extensionHostEnv - }; - - return { - type: 'ok', - value: { - authority, - options - } - }; - } catch (err) { - if (err instanceof RemoteAuthorityResolverError) { - return { - type: 'error', - error: { - code: err._code, - message: err._message, - detail: err._detail - } - }; - } - throw err; - } - } - - public $startExtensionHost(enabledExtensionIds: ExtensionIdentifier[]): Promise { - this._registry.keepOnly(enabledExtensionIds); - return this._startExtensionHost(); - } - - public $activateByEvent(activationEvent: string): Promise { - return ( - this._readyToRunExtensions.wait() - .then(_ => this._activateByEvent(activationEvent, false)) - ); - } - - public async $activate(extensionId: ExtensionIdentifier, activationEvent: string): Promise { - await this._readyToRunExtensions.wait(); - if (!this._registry.getExtensionDescription(extensionId)) { - // unknown extension => ignore - return false; - } - await this._activateById(extensionId, new ExtensionActivatedByEvent(false, activationEvent)); - return true; - } - - public async $deltaExtensions(toAdd: IExtensionDescription[], toRemove: ExtensionIdentifier[]): Promise { - toAdd.forEach((extension) => (extension).extensionLocation = URI.revive(extension.extensionLocation)); - - const trie = await this.getExtensionPathIndex(); - - await Promise.all(toRemove.map(async (extensionId) => { - const extensionDescription = this._registry.getExtensionDescription(extensionId); - if (!extensionDescription) { - return; - } - const realpathValue = await this._hostUtils.realpath(extensionDescription.extensionLocation.fsPath); - trie.delete(URI.file(realpathValue).fsPath); - })); - - await Promise.all(toAdd.map(async (extensionDescription) => { - const realpathValue = await this._hostUtils.realpath(extensionDescription.extensionLocation.fsPath); - trie.set(URI.file(realpathValue).fsPath, extensionDescription); - })); - - this._registry.deltaExtensions(toAdd, toRemove); - return Promise.resolve(undefined); - } - - public async $test_latency(n: number): Promise { - return n; - } - - public async $test_up(b: VSBuffer): Promise { - return b.byteLength; - } - - public async $test_down(size: number): Promise { - let buff = VSBuffer.alloc(size); - let value = Math.random() % 256; - for (let i = 0; i < size; i++) { - buff.writeUInt8(value, i); - } - return buff; - } - - public async $setRemoteEnvironment(env: { [key: string]: string | null }): Promise { - if (!this._initData.remote.isRemote) { - return; - } - - for (const key in env) { - const value = env[key]; - if (value === null) { - delete process.env[key]; - } else { - process.env[key] = value; - } - } - } -} - -async function loadCommonJSModule(logService: ILogService, modulePath: string, activationTimesBuilder: ExtensionActivationTimesBuilder): Promise { - - // fake commonjs world - const module = { exports: {} }; - //@ts-ignore - self['module'] = module; - //@ts-ignore - self['exports'] = module.exports; - - // that's improper but might help extensions that aren't author correctly - // @ts-ignore - self['window'] = self; - - // import the single (!) script, make sure it's a JS-file - const suffix = '.js'; - if (endsWith(modulePath, suffix)) { - importScripts(modulePath); - } else { - importScripts(modulePath + suffix); - } - - // return what it exported - return module.exports as T; -} - -type TelemetryActivationEvent = { - id: string; - name: string; - extensionVersion: string; - publisherDisplayName: string; - activationEvents: string | null; - isBuiltin: boolean; - reason: string; -}; - -function getTelemetryActivationEvent(extensionDescription: IExtensionDescription, reason: ExtensionActivationReason): TelemetryActivationEvent { - const reasonStr = reason instanceof ExtensionActivatedByEvent ? reason.activationEvent : - reason instanceof ExtensionActivatedByAPI ? 'api' : - ''; - const event = { - id: extensionDescription.identifier.value, - name: extensionDescription.name, - extensionVersion: extensionDescription.version, - publisherDisplayName: extensionDescription.publisher, - activationEvents: extensionDescription.activationEvents ? extensionDescription.activationEvents.join(',') : null, - isBuiltin: extensionDescription.isBuiltin, - reason: reasonStr - }; - - return event; -} diff --git a/src/vs/workbench/services/extensions/worker/extensionHostMain.ts b/src/vs/workbench/services/extensions/worker/extensionHostMain.ts deleted file mode 100644 index 54094e12547..00000000000 --- a/src/vs/workbench/services/extensions/worker/extensionHostMain.ts +++ /dev/null @@ -1,154 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { timeout } from 'vs/base/common/async'; -import * as errors from 'vs/base/common/errors'; -import { DisposableStore } from 'vs/base/common/lifecycle'; -import { URI, setUriThrowOnMissingScheme } from 'vs/base/common/uri'; -import { IURITransformer } from 'vs/base/common/uriIpc'; -import { IMessagePassingProtocol } from 'vs/base/parts/ipc/common/ipc'; -import { IInitData, MainContext, MainThreadConsoleShape } from 'vs/workbench/api/common/extHost.protocol'; -import { ExtHostConfiguration } from 'vs/workbench/api/common/extHostConfiguration'; -import { ExtHostExtensionService, IHostUtils } from './extHostExtensionService'; -import { ExtHostLogService } from 'vs/workbench/api/common/extHostLogService'; -import { ExtHostWorkspace } from 'vs/workbench/api/common/extHostWorkspace'; -import { RPCProtocol } from 'vs/workbench/services/extensions/common/rpcProtocol'; -import { IExtensionDescription } from 'vs/platform/extensions/common/extensions'; -import { withNullAsUndefined } from 'vs/base/common/types'; -import { ILogService } from 'vs/platform/log/common/log'; - -// we don't (yet) throw when extensions parse -// uris that have no scheme -setUriThrowOnMissingScheme(false); - -export interface IExitFn { - (code?: number): any; -} - -export interface IConsolePatchFn { - (mainThreadConsole: MainThreadConsoleShape): any; -} - -export interface ILogServiceFn { - (initData: IInitData): ILogService; -} - -export class ExtensionHostMain { - - private _isTerminating: boolean; - private readonly _hostUtils: IHostUtils; - private readonly _extensionService: ExtHostExtensionService; - private readonly _disposables = new DisposableStore(); - - constructor( - protocol: IMessagePassingProtocol, - initData: IInitData, - hostUtils: IHostUtils, - consolePatchFn: IConsolePatchFn, - logServiceFn: ILogServiceFn, - uriTransformer: IURITransformer | null - ) { - this._isTerminating = false; - this._hostUtils = hostUtils; - const rpcProtocol = new RPCProtocol(protocol, null, uriTransformer); - - // ensure URIs are transformed and revived - initData = ExtensionHostMain._transform(initData, rpcProtocol); - - // allow to patch console - consolePatchFn(rpcProtocol.getProxy(MainContext.MainThreadConsole)); - - // services - const extHostLogService = new ExtHostLogService(logServiceFn(initData), initData.logsLocation.fsPath); - this._disposables.add(extHostLogService); - - const extHostWorkspace = new ExtHostWorkspace(rpcProtocol, extHostLogService, withNullAsUndefined(initData.workspace)); - - extHostLogService.info('extension host started'); - extHostLogService.trace('initData', initData); - - const extHostConfiguraiton = new ExtHostConfiguration(rpcProtocol.getProxy(MainContext.MainThreadConfiguration), extHostWorkspace); - this._extensionService = new ExtHostExtensionService( - hostUtils, - initData, - rpcProtocol, - extHostWorkspace, - extHostConfiguraiton, - initData.environment, - extHostLogService, - uriTransformer - ); - - // error forwarding and stack trace scanning - Error.stackTraceLimit = 100; // increase number of stack frames (from 10, https://github.com/v8/v8/wiki/Stack-Trace-API) - const extensionErrors = new WeakMap(); - this._extensionService.getExtensionPathIndex().then(map => { - (Error).prepareStackTrace = (error: Error, stackTrace: errors.V8CallSite[]) => { - let stackTraceMessage = ''; - let extension: IExtensionDescription | undefined; - let fileName: string; - for (const call of stackTrace) { - stackTraceMessage += `\n\tat ${call.toString()}`; - fileName = call.getFileName(); - if (!extension && fileName) { - extension = map.findSubstr(fileName); - } - - } - extensionErrors.set(error, extension); - return `${error.name || 'Error'}: ${error.message || ''}${stackTraceMessage}`; - }; - }); - - const mainThreadExtensions = rpcProtocol.getProxy(MainContext.MainThreadExtensionService); - const mainThreadErrors = rpcProtocol.getProxy(MainContext.MainThreadErrors); - errors.setUnexpectedErrorHandler(err => { - const data = errors.transformErrorForSerialization(err); - const extension = extensionErrors.get(err); - if (extension) { - mainThreadExtensions.$onExtensionRuntimeError(extension.identifier, data); - } else { - mainThreadErrors.$onUnexpectedError(data); - } - }); - } - - terminate(): void { - if (this._isTerminating) { - // we are already shutting down... - return; - } - this._isTerminating = true; - - this._disposables.dispose(); - - errors.setUnexpectedErrorHandler((err) => { - // TODO: write to log once we have one - }); - - const extensionsDeactivated = this._extensionService.deactivateAll(); - - // Give extensions 1 second to wrap up any async dispose, then exit in at most 4 seconds - setTimeout(() => { - Promise.race([timeout(4000), extensionsDeactivated]).finally(() => this._hostUtils.exit()); - }, 1000); - } - - private static _transform(initData: IInitData, rpcProtocol: RPCProtocol): IInitData { - initData.extensions.forEach((ext) => (ext).extensionLocation = URI.revive(rpcProtocol.transformIncomingURIs(ext.extensionLocation))); - initData.environment.appRoot = URI.revive(rpcProtocol.transformIncomingURIs(initData.environment.appRoot)); - initData.environment.appSettingsHome = URI.revive(rpcProtocol.transformIncomingURIs(initData.environment.appSettingsHome)); - const extDevLocs = initData.environment.extensionDevelopmentLocationURI; - if (extDevLocs) { - initData.environment.extensionDevelopmentLocationURI = extDevLocs.map(url => URI.revive(rpcProtocol.transformIncomingURIs(url))); - } - initData.environment.extensionTestsLocationURI = URI.revive(rpcProtocol.transformIncomingURIs(initData.environment.extensionTestsLocationURI)); - initData.environment.globalStorageHome = URI.revive(rpcProtocol.transformIncomingURIs(initData.environment.globalStorageHome)); - initData.environment.userHome = URI.revive(rpcProtocol.transformIncomingURIs(initData.environment.userHome)); - initData.logsLocation = URI.revive(rpcProtocol.transformIncomingURIs(initData.logsLocation)); - initData.workspace = rpcProtocol.transformIncomingURIs(initData.workspace); - return initData; - } -} diff --git a/src/vs/workbench/services/extensions/worker/extensionHostWorker.ts b/src/vs/workbench/services/extensions/worker/extensionHostWorker.ts index 61a30631c8b..7d42bf2044d 100644 --- a/src/vs/workbench/services/extensions/worker/extensionHostWorker.ts +++ b/src/vs/workbench/services/extensions/worker/extensionHostWorker.ts @@ -9,9 +9,10 @@ import { VSBuffer } from 'vs/base/common/buffer'; import { Emitter } from 'vs/base/common/event'; import { isMessageOfType, MessageType, createMessageOfType } from 'vs/workbench/services/extensions/common/extensionHostProtocol'; import { IInitData } from 'vs/workbench/api/common/extHost.protocol'; -import { IHostUtils } from 'vs/workbench/services/extensions/worker/extHostExtensionService'; -import { ExtensionHostMain } from 'vs/workbench/services/extensions/worker/extensionHostMain'; +import { ExtensionHostMain } from 'vs/workbench/services/extensions/common/extensionHostMain'; import { ConsoleLogService } from 'vs/platform/log/common/log'; +import { IHostUtils } from 'vs/workbench/api/common/extHostExtensionService'; +import 'vs/workbench/services/extensions/worker/extHost.services'; // worker-self declare namespace self { @@ -24,10 +25,11 @@ self.close = () => console.trace('An extension called terminate and this was pre let onTerminate = nativeClose; const hostUtil = new class implements IHostUtils { - exit(code?: number | undefined): void { + _serviceBrand: any; + exit(_code?: number | undefined): void { nativeClose(); } - async exists(path: string): Promise { + async exists(_path: string): Promise { return true; } async realpath(path: string): Promise {