extHost.api.impl.ts 32.3 KB
Newer Older
E
Erich Gamma 已提交
1 2 3 4 5 6
/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/
'use strict';

7
import { Emitter } from 'vs/base/common/event';
8
import { TrieMap } from 'vs/base/common/map';
J
Johannes Rieken 已提交
9
import { score } from 'vs/editor/common/modes/languageSelector';
10
import * as Platform from 'vs/base/common/platform';
E
Erich Gamma 已提交
11
import * as errors from 'vs/base/common/errors';
12 13
import product from 'vs/platform/node/product';
import pkg from 'vs/platform/node/package';
J
Johannes Rieken 已提交
14
import { ExtHostFileSystemEventService } from 'vs/workbench/api/node/extHostFileSystemEventService';
J
Johannes Rieken 已提交
15
import { ExtHostDocumentsAndEditors } from 'vs/workbench/api/node/extHostDocumentsAndEditors';
J
Johannes Rieken 已提交
16
import { ExtHostDocuments } from 'vs/workbench/api/node/extHostDocuments';
17
import { ExtHostDocumentContentProvider } from 'vs/workbench/api/node/extHostDocumentContentProviders';
J
Johannes Rieken 已提交
18 19 20
import { ExtHostDocumentSaveParticipant } from 'vs/workbench/api/node/extHostDocumentSaveParticipant';
import { ExtHostConfiguration } from 'vs/workbench/api/node/extHostConfiguration';
import { ExtHostDiagnostics } from 'vs/workbench/api/node/extHostDiagnostics';
S
Sandeep Somavarapu 已提交
21
import { ExtHostTreeViews } from 'vs/workbench/api/node/extHostTreeViews';
J
Johannes Rieken 已提交
22 23
import { ExtHostWorkspace } from 'vs/workbench/api/node/extHostWorkspace';
import { ExtHostQuickOpen } from 'vs/workbench/api/node/extHostQuickOpen';
24
import { ExtHostProgress } from 'vs/workbench/api/node/extHostProgress';
J
Joao Moreno 已提交
25
import { ExtHostSCM } from 'vs/workbench/api/node/extHostSCM';
J
Johannes Rieken 已提交
26 27 28 29 30 31
import { ExtHostHeapService } from 'vs/workbench/api/node/extHostHeapService';
import { ExtHostStatusBar } from 'vs/workbench/api/node/extHostStatusBar';
import { ExtHostCommands } from 'vs/workbench/api/node/extHostCommands';
import { ExtHostOutputService } from 'vs/workbench/api/node/extHostOutputService';
import { ExtHostTerminalService } from 'vs/workbench/api/node/extHostTerminalService';
import { ExtHostMessageService } from 'vs/workbench/api/node/extHostMessageService';
J
Johannes Rieken 已提交
32
import { ExtHostEditors } from 'vs/workbench/api/node/extHostTextEditors';
J
Johannes Rieken 已提交
33 34
import { ExtHostLanguages } from 'vs/workbench/api/node/extHostLanguages';
import { ExtHostLanguageFeatures } from 'vs/workbench/api/node/extHostLanguageFeatures';
35
import { ExtHostApiCommands } from 'vs/workbench/api/node/extHostApiCommands';
36
import { ExtHostTask } from 'vs/workbench/api/node/extHostTask';
37
import { ExtHostDebugService } from 'vs/workbench/api/node/extHostDebugService';
C
Christof Marti 已提交
38
import { ExtHostCredentials } from 'vs/workbench/api/node/extHostCredentials';
J
Johannes Rieken 已提交
39
import * as extHostTypes from 'vs/workbench/api/node/extHostTypes';
E
Erich Gamma 已提交
40 41 42
import URI from 'vs/base/common/uri';
import Severity from 'vs/base/common/severity';
import EditorCommon = require('vs/editor/common/editorCommon');
J
Johannes Rieken 已提交
43 44 45
import { IExtensionDescription } from 'vs/platform/extensions/common/extensions';
import { ExtHostExtensionService } from 'vs/workbench/api/node/extHostExtensionService';
import { TPromise } from 'vs/base/common/winjs.base';
46
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
J
Johannes Rieken 已提交
47
import { CancellationTokenSource } from 'vs/base/common/cancellation';
48
import * as vscode from 'vscode';
E
Erich Gamma 已提交
49
import * as paths from 'vs/base/common/paths';
50
import { MainContext, ExtHostContext, IInitData } from './extHost.protocol';
51
import * as languageConfiguration from 'vs/editor/common/modes/languageConfiguration';
52
import { TextEditorCursorStyle } from 'vs/editor/common/config/editorOptions';
B
Benjamin Pasero 已提交
53 54 55
import { ExtHostThreadService } from 'vs/workbench/services/thread/node/extHostThreadService';
import { ProxyIdentifier } from 'vs/workbench/services/thread/common/threadService';
import { ExtHostDialogs } from 'vs/workbench/api/node/extHostDialogs';
E
Erich Gamma 已提交
56

57
export interface IExtensionApiFactory {
58
	(extension: IExtensionDescription): typeof vscode;
59 60
}

61
function proposedApiFunction<T>(extension: IExtensionDescription, fn: T): T {
62
	if (extension.enableProposedApi) {
63 64 65
		return fn;
	} else {
		return <any>(() => {
66
			throw new Error(`[${extension.id}]: Proposed API is only available when running out of dev or with the following command line switch: --enable-proposed-api ${extension.id}`);
67 68 69 70
		});
	}
}

E
Erich Gamma 已提交
71
/**
72
 * This method instantiates and returns the extension API surface
E
Erich Gamma 已提交
73
 */
74 75
export function createApiFactory(
	initData: IInitData,
76
	threadService: ExtHostThreadService,
77 78 79
	extensionService: ExtHostExtensionService,
	telemetryService: ITelemetryService
): IExtensionApiFactory {
80

81
	// Addressable instances
82 83 84 85 86 87 88 89 90
	const extHostHeapService = threadService.set(ExtHostContext.ExtHostHeapService, new ExtHostHeapService());
	const extHostDocumentsAndEditors = threadService.set(ExtHostContext.ExtHostDocumentsAndEditors, new ExtHostDocumentsAndEditors(threadService));
	const extHostDocuments = threadService.set(ExtHostContext.ExtHostDocuments, new ExtHostDocuments(threadService, extHostDocumentsAndEditors));
	const extHostDocumentContentProviders = threadService.set(ExtHostContext.ExtHostDocumentContentProviders, new ExtHostDocumentContentProvider(threadService, extHostDocumentsAndEditors));
	const extHostDocumentSaveParticipant = threadService.set(ExtHostContext.ExtHostDocumentSaveParticipant, new ExtHostDocumentSaveParticipant(extHostDocuments, threadService.get(MainContext.MainThreadWorkspace)));
	const extHostEditors = threadService.set(ExtHostContext.ExtHostEditors, new ExtHostEditors(threadService, extHostDocumentsAndEditors));
	const extHostCommands = threadService.set(ExtHostContext.ExtHostCommands, new ExtHostCommands(threadService, extHostHeapService));
	const extHostTreeViews = threadService.set(ExtHostContext.ExtHostTreeViews, new ExtHostTreeViews(threadService.get(MainContext.MainThreadTreeViews), extHostCommands));
	const extHostWorkspace = threadService.set(ExtHostContext.ExtHostWorkspace, new ExtHostWorkspace(threadService, initData.workspace));
91
	const extHostDebugService = threadService.set(ExtHostContext.ExtHostDebugService, new ExtHostDebugService(threadService, extHostWorkspace));
92 93 94 95 96 97 98 99 100 101 102 103 104 105
	const extHostConfiguration = threadService.set(ExtHostContext.ExtHostConfiguration, new ExtHostConfiguration(threadService.get(MainContext.MainThreadConfiguration), extHostWorkspace, initData.configuration));
	const extHostDiagnostics = threadService.set(ExtHostContext.ExtHostDiagnostics, new ExtHostDiagnostics(threadService));
	const languageFeatures = threadService.set(ExtHostContext.ExtHostLanguageFeatures, new ExtHostLanguageFeatures(threadService, extHostDocuments, extHostCommands, extHostHeapService, extHostDiagnostics));
	const extHostFileSystemEvent = threadService.set(ExtHostContext.ExtHostFileSystemEventService, new ExtHostFileSystemEventService());
	const extHostQuickOpen = threadService.set(ExtHostContext.ExtHostQuickOpen, new ExtHostQuickOpen(threadService));
	const extHostTerminalService = threadService.set(ExtHostContext.ExtHostTerminalService, new ExtHostTerminalService(threadService));
	const extHostSCM = threadService.set(ExtHostContext.ExtHostSCM, new ExtHostSCM(threadService, extHostCommands));
	const extHostTask = threadService.set(ExtHostContext.ExtHostTask, new ExtHostTask(threadService));
	const extHostCredentials = threadService.set(ExtHostContext.ExtHostCredentials, new ExtHostCredentials(threadService));
	threadService.set(ExtHostContext.ExtHostExtensionService, extensionService);

	// Check that no named customers are missing
	const expected: ProxyIdentifier<any>[] = Object.keys(ExtHostContext).map((key) => ExtHostContext[key]);
	threadService.assertRegistered(expected);
106

107 108
	// Other instances
	const extHostMessageService = new ExtHostMessageService(threadService);
109
	const extHostDialogs = new ExtHostDialogs(threadService);
110
	const extHostStatusBar = new ExtHostStatusBar(threadService);
111
	const extHostProgress = new ExtHostProgress(threadService.get(MainContext.MainThreadProgress));
112 113
	const extHostOutputService = new ExtHostOutputService(threadService);
	const extHostLanguages = new ExtHostLanguages(threadService);
114

115 116
	// Register API-ish commands
	ExtHostApiCommands.register(extHostCommands);
117

118
	return function (extension: IExtensionDescription): typeof vscode {
119

120
		if (extension.enableProposedApi && !extension.isBuiltin) {
121

122 123 124 125
			if (
				!initData.environment.enableProposedApiForAll &&
				initData.environment.enableProposedApiFor.indexOf(extension.id) < 0
			) {
126
				extension.enableProposedApi = false;
127
				console.error(`Extension '${extension.id} cannot use PROPOSED API (must started out of dev or enabled via --enable-proposed-api)`);
128 129

			} else {
130 131 132
				// proposed api is available when developing or when an extension was explicitly
				// spelled out via a command line argument
				console.warn(`Extension '${extension.id}' uses PROPOSED API which is subject to change and removal without notice.`);
133
			}
134 135
		}

136 137 138 139 140 141 142 143 144 145 146 147 148 149
		const apiUsage = new class {
			private _seen = new Set<string>();
			publicLog(apiName: string) {
				if (this._seen.has(apiName)) {
					return undefined;
				}
				this._seen.add(apiName);
				return telemetryService.publicLog('apiUsage', {
					name: apiName,
					extension: extension.id
				});
			}
		};

150 151
		// namespace: commands
		const commands: typeof vscode.commands = {
152 153
			registerCommand<T>(id: string, command: <T>(...args: any[]) => T | Thenable<T>, thisArgs?: any): vscode.Disposable {
				return extHostCommands.registerCommand(id, command, thisArgs);
154
			},
155
			registerTextEditorCommand(id: string, callback: (textEditor: vscode.TextEditor, edit: vscode.TextEditorEdit, ...args: any[]) => void, thisArg?: any): vscode.Disposable {
156
				return extHostCommands.registerCommand(id, (...args: any[]): any => {
157 158 159
					let activeTextEditor = extHostEditors.getActiveTextEditor();
					if (!activeTextEditor) {
						console.warn('Cannot execute ' + id + ' because there is no active text editor.');
160
						return undefined;
161
					}
162 163 164 165 166 167 168 169 170 171

					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) => {
172
						console.warn('An error occurred while running command ' + id, err);
173
					});
174
				});
175 176
			},
			registerDiffInformationCommand: proposedApiFunction(extension, (id: string, callback: (diff: vscode.LineChange[], ...args: any[]) => any, thisArg?: any): vscode.Disposable => {
177 178 179 180 181 182 183 184 185 186
				return extHostCommands.registerCommand(id, async (...args: any[]) => {
					let activeTextEditor = extHostEditors.getActiveTextEditor();
					if (!activeTextEditor) {
						console.warn('Cannot execute ' + id + ' because there is no active text editor.');
						return undefined;
					}

					const diff = await extHostEditors.getDiffInformation(activeTextEditor.id);
					callback.apply(thisArg, [diff, ...args]);
				});
187
			}),
188
			executeCommand<T>(id: string, ...args: any[]): Thenable<T> {
189
				return extHostCommands.executeCommand<T>(id, ...args);
190
			},
191 192 193
			getCommands(filterInternal: boolean = false): Thenable<string[]> {
				return extHostCommands.getCommands(filterInternal);
			}
194
		};
195

196 197
		// namespace: env
		const env: typeof vscode.env = Object.freeze({
198 199
			get machineId() { return initData.telemetryInfo.machineId; },
			get sessionId() { return initData.telemetryInfo.sessionId; },
200 201 202
			get language() { return Platform.language; },
			get appName() { return product.nameLong; }
		});
E
Erich Gamma 已提交
203

204 205 206
		// namespace: extensions
		const extensions: typeof vscode.extensions = {
			getExtension(extensionId: string): Extension<any> {
207
				let desc = extensionService.getExtensionDescription(extensionId);
208 209 210
				if (desc) {
					return new Extension(extensionService, desc);
				}
211
				return undefined;
212 213
			},
			get all(): Extension<any>[] {
214
				return extensionService.getAllExtensionDescriptions().map((desc) => new Extension(extensionService, desc));
E
Erich Gamma 已提交
215
			}
216
		};
E
Erich Gamma 已提交
217

218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237
		// namespace: languages
		const languages: typeof vscode.languages = {
			createDiagnosticCollection(name?: string): vscode.DiagnosticCollection {
				return extHostDiagnostics.createDiagnosticCollection(name);
			},
			getLanguages(): TPromise<string[]> {
				return extHostLanguages.getLanguages();
			},
			match(selector: vscode.DocumentSelector, document: vscode.TextDocument): number {
				return score(selector, <any>document.uri, document.languageId);
			},
			registerCodeActionsProvider(selector: vscode.DocumentSelector, provider: vscode.CodeActionProvider): vscode.Disposable {
				return languageFeatures.registerCodeActionProvider(selector, provider);
			},
			registerCodeLensProvider(selector: vscode.DocumentSelector, provider: vscode.CodeLensProvider): vscode.Disposable {
				return languageFeatures.registerCodeLensProvider(selector, provider);
			},
			registerDefinitionProvider(selector: vscode.DocumentSelector, provider: vscode.DefinitionProvider): vscode.Disposable {
				return languageFeatures.registerDefinitionProvider(selector, provider);
			},
M
Matt Bierner 已提交
238 239
			registerImplementationProvider(selector: vscode.DocumentSelector, provider: vscode.ImplementationProvider): vscode.Disposable {
				return languageFeatures.registerImplementationProvider(selector, provider);
240
			},
241 242 243
			registerTypeDefinitionProvider(selector: vscode.DocumentSelector, provider: vscode.TypeDefinitionProvider): vscode.Disposable {
				return languageFeatures.registerTypeDefinitionProvider(selector, provider);
			},
244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274
			registerHoverProvider(selector: vscode.DocumentSelector, provider: vscode.HoverProvider): vscode.Disposable {
				return languageFeatures.registerHoverProvider(selector, provider);
			},
			registerDocumentHighlightProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentHighlightProvider): vscode.Disposable {
				return languageFeatures.registerDocumentHighlightProvider(selector, provider);
			},
			registerReferenceProvider(selector: vscode.DocumentSelector, provider: vscode.ReferenceProvider): vscode.Disposable {
				return languageFeatures.registerReferenceProvider(selector, provider);
			},
			registerRenameProvider(selector: vscode.DocumentSelector, provider: vscode.RenameProvider): vscode.Disposable {
				return languageFeatures.registerRenameProvider(selector, provider);
			},
			registerDocumentSymbolProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentSymbolProvider): vscode.Disposable {
				return languageFeatures.registerDocumentSymbolProvider(selector, provider);
			},
			registerWorkspaceSymbolProvider(provider: vscode.WorkspaceSymbolProvider): vscode.Disposable {
				return languageFeatures.registerWorkspaceSymbolProvider(provider);
			},
			registerDocumentFormattingEditProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentFormattingEditProvider): vscode.Disposable {
				return languageFeatures.registerDocumentFormattingEditProvider(selector, provider);
			},
			registerDocumentRangeFormattingEditProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentRangeFormattingEditProvider): vscode.Disposable {
				return languageFeatures.registerDocumentRangeFormattingEditProvider(selector, provider);
			},
			registerOnTypeFormattingEditProvider(selector: vscode.DocumentSelector, provider: vscode.OnTypeFormattingEditProvider, firstTriggerCharacter: string, ...moreTriggerCharacters: string[]): vscode.Disposable {
				return languageFeatures.registerOnTypeFormattingEditProvider(selector, provider, [firstTriggerCharacter].concat(moreTriggerCharacters));
			},
			registerSignatureHelpProvider(selector: vscode.DocumentSelector, provider: vscode.SignatureHelpProvider, ...triggerCharacters: string[]): vscode.Disposable {
				return languageFeatures.registerSignatureHelpProvider(selector, provider, triggerCharacters);
			},
			registerCompletionItemProvider(selector: vscode.DocumentSelector, provider: vscode.CompletionItemProvider, ...triggerCharacters: string[]): vscode.Disposable {
275
				return languageFeatures.registerCompletionItemProvider(selector, provider, triggerCharacters);
276 277 278 279 280 281
			},
			registerDocumentLinkProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentLinkProvider): vscode.Disposable {
				return languageFeatures.registerDocumentLinkProvider(selector, provider);
			},
			setLanguageConfiguration: (language: string, configuration: vscode.LanguageConfiguration): vscode.Disposable => {
				return languageFeatures.setLanguageConfiguration(language, configuration);
282 283 284 285 286
			},
			// proposed API
			registerColorProvider: proposedApiFunction(extension, (selector: vscode.DocumentSelector, provider: vscode.DocumentColorProvider) => {
				return languageFeatures.registerColorProvider(selector, provider);
			})
287
		};
E
Erich Gamma 已提交
288

289 290 291 292 293 294 295 296
		// namespace: window
		const window: typeof vscode.window = {
			get activeTextEditor() {
				return extHostEditors.getActiveTextEditor();
			},
			get visibleTextEditors() {
				return extHostEditors.getVisibleTextEditors();
			},
J
Johannes Rieken 已提交
297
			showTextDocument(documentOrUri: vscode.TextDocument | vscode.Uri, columnOrOptions?: vscode.ViewColumn | vscode.TextDocumentShowOptions, preserveFocus?: boolean): TPromise<vscode.TextEditor> {
B
Benjamin Pasero 已提交
298
				let documentPromise: TPromise<vscode.TextDocument>;
J
Johannes Rieken 已提交
299 300
				if (URI.isUri(documentOrUri)) {
					documentPromise = TPromise.wrap(workspace.openTextDocument(documentOrUri));
B
Benjamin Pasero 已提交
301
				} else {
J
Johannes Rieken 已提交
302
					documentPromise = TPromise.wrap(<vscode.TextDocument>documentOrUri);
B
Benjamin Pasero 已提交
303 304 305 306
				}
				return documentPromise.then(document => {
					return extHostEditors.showTextDocument(document, columnOrOptions, preserveFocus);
				});
307 308 309 310
			},
			createTextEditorDecorationType(options: vscode.DecorationRenderOptions): vscode.TextEditorDecorationType {
				return extHostEditors.createTextEditorDecorationType(options);
			},
311 312 313
			onDidChangeActiveTextEditor(listener, thisArg?, disposables?) {
				return extHostEditors.onDidChangeActiveTextEditor(listener, thisArg, disposables);
			},
314 315 316
			onDidChangeVisibleTextEditors(listener, thisArg, disposables) {
				return extHostEditors.onDidChangeVisibleTextEditors(listener, thisArg, disposables);
			},
317
			onDidChangeTextEditorSelection(listener: (e: vscode.TextEditorSelectionChangeEvent) => any, thisArgs?: any, disposables?: extHostTypes.Disposable[]) {
318 319
				return extHostEditors.onDidChangeTextEditorSelection(listener, thisArgs, disposables);
			},
320
			onDidChangeTextEditorOptions(listener: (e: vscode.TextEditorOptionsChangeEvent) => any, thisArgs?: any, disposables?: extHostTypes.Disposable[]) {
321 322 323 324 325
				return extHostEditors.onDidChangeTextEditorOptions(listener, thisArgs, disposables);
			},
			onDidChangeTextEditorViewColumn(listener, thisArg?, disposables?) {
				return extHostEditors.onDidChangeTextEditorViewColumn(listener, thisArg, disposables);
			},
326 327 328
			onDidCloseTerminal(listener, thisArg?, disposables?) {
				return extHostTerminalService.onDidCloseTerminal(listener, thisArg, disposables);
			},
J
Joao Moreno 已提交
329
			showInformationMessage(message, first, ...rest) {
330
				return extHostMessageService.showMessage(extension.id, Severity.Info, message, first, rest);
331
			},
J
Joao Moreno 已提交
332
			showWarningMessage(message, first, ...rest) {
333
				return extHostMessageService.showMessage(extension.id, Severity.Warning, message, first, rest);
334
			},
J
Joao Moreno 已提交
335
			showErrorMessage(message, first, ...rest) {
336
				return extHostMessageService.showMessage(extension.id, Severity.Error, message, first, rest);
337
			},
338
			showQuickPick(items: any, options: vscode.QuickPickOptions, token?: vscode.CancellationToken) {
339 340 341 342 343 344
				return extHostQuickOpen.showQuickPick(items, options, token);
			},
			showInputBox(options?: vscode.InputBoxOptions, token?: vscode.CancellationToken) {
				return extHostQuickOpen.showInput(options, token);
			},
			createStatusBarItem(position?: vscode.StatusBarAlignment, priority?: number): vscode.StatusBarItem {
345
				return extHostStatusBar.createStatusBarEntry(extension.id, <number>position, priority);
346 347 348 349
			},
			setStatusBarMessage(text: string, timeoutOrThenable?: number | Thenable<any>): vscode.Disposable {
				return extHostStatusBar.setStatusBarMessage(text, timeoutOrThenable);
			},
350
			withScmProgress<R>(task: (progress: vscode.Progress<number>) => Thenable<R>) {
351
				console.warn(`[Deprecation Warning] function 'withScmProgress' is deprecated and should no longer be used. Use 'withProgress' instead.`);
352
				return extHostProgress.withProgress(extension, { location: extHostTypes.ProgressLocation.SourceControl }, (progress, token) => task({ report(n: number) { /*noop*/ } }));
J
Johannes Rieken 已提交
353 354 355
			},
			withProgress<R>(options: vscode.ProgressOptions, task: (progress: vscode.Progress<{ message?: string; percentage?: number }>) => Thenable<R>) {
				return extHostProgress.withProgress(extension, options, task);
356
			},
357 358 359
			createOutputChannel(name: string): vscode.OutputChannel {
				return extHostOutputService.createOutputChannel(name);
			},
360 361 362 363
			createTerminal(nameOrOptions: vscode.TerminalOptions | string, shellPath?: string, shellArgs?: string[]): vscode.Terminal {
				if (typeof nameOrOptions === 'object') {
					return extHostTerminalService.createTerminalFromOptions(<vscode.TerminalOptions>nameOrOptions);
				}
D
Daniel Imms 已提交
364
				return extHostTerminalService.createTerminal(<string>nameOrOptions, shellPath, shellArgs);
365
			},
S
Sandeep Somavarapu 已提交
366 367 368
			registerTreeDataProvider(viewId: string, treeDataProvider: vscode.TreeDataProvider<any>): vscode.Disposable {
				return extHostTreeViews.registerTreeDataProvider(viewId, treeDataProvider);
			},
369 370
			// proposed API
			sampleFunction: proposedApiFunction(extension, () => {
371
				return extHostMessageService.showMessage(extension.id, Severity.Info, 'Hello Proposed Api!', {}, []);
372
			}),
373 374 375
			showOpenDialog: proposedApiFunction(extension, () => {
				return extHostDialogs.showOpenDialog();
			})
376
		};
E
Erich Gamma 已提交
377

378 379 380
		// namespace: workspace
		const workspace: typeof vscode.workspace = {
			get rootPath() {
381
				apiUsage.publicLog('workspace#rootPath');
382 383 384 385 386
				return extHostWorkspace.getPath();
			},
			set rootPath(value) {
				throw errors.readonly();
			},
387 388
			getWorkspaceFolder(resource) {
				return extHostWorkspace.getWorkspaceFolder(resource);
389
			},
390
			get workspaceFolders() {
391
				apiUsage.publicLog('workspace#workspaceFolders');
392
				return extHostWorkspace.getWorkspaceFolders();
393
			},
394
			onDidChangeWorkspaceFolders: function (listener, thisArgs?, disposables?) {
395
				apiUsage.publicLog('workspace#onDidChangeWorkspaceFolders');
396
				return extHostWorkspace.onDidChangeWorkspace(listener, thisArgs, disposables);
397
			},
J
Johannes Rieken 已提交
398 399
			asRelativePath: (pathOrUri, includeWorkspace) => {
				return extHostWorkspace.getRelativePath(pathOrUri, includeWorkspace);
400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418
			},
			findFiles: (include, exclude, maxResults?, token?) => {
				return extHostWorkspace.findFiles(include, exclude, maxResults, token);
			},
			saveAll: (includeUntitled?) => {
				return extHostWorkspace.saveAll(includeUntitled);
			},
			applyEdit(edit: vscode.WorkspaceEdit): TPromise<boolean> {
				return extHostWorkspace.appyEdit(edit);
			},
			createFileSystemWatcher: (pattern, ignoreCreate, ignoreChange, ignoreDelete): vscode.FileSystemWatcher => {
				return extHostFileSystemEvent.createFileSystemWatcher(pattern, ignoreCreate, ignoreChange, ignoreDelete);
			},
			get textDocuments() {
				return extHostDocuments.getAllDocumentData().map(data => data.document);
			},
			set textDocuments(value) {
				throw errors.readonly();
			},
419
			openTextDocument(uriOrFileNameOrOptions?: vscode.Uri | string | { language?: string; content?: string; }) {
B
Benjamin Pasero 已提交
420 421
				let uriPromise: TPromise<URI>;

422
				let options = uriOrFileNameOrOptions as { language?: string; content?: string; };
B
Benjamin Pasero 已提交
423 424 425 426 427 428
				if (!options || typeof options.language === 'string') {
					uriPromise = extHostDocuments.createDocumentData(options);
				} else if (typeof uriOrFileNameOrOptions === 'string') {
					uriPromise = TPromise.as(URI.file(uriOrFileNameOrOptions));
				} else if (uriOrFileNameOrOptions instanceof URI) {
					uriPromise = TPromise.as(<URI>uriOrFileNameOrOptions);
429
				} else {
B
Benjamin Pasero 已提交
430
					throw new Error('illegal argument - uriOrFileNameOrOptions');
431
				}
B
Benjamin Pasero 已提交
432 433 434 435 436 437

				return uriPromise.then(uri => {
					return extHostDocuments.ensureDocumentData(uri).then(() => {
						const data = extHostDocuments.getDocumentData(uri);
						return data && data.document;
					});
438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453
				});
			},
			onDidOpenTextDocument: (listener, thisArgs?, disposables?) => {
				return extHostDocuments.onDidAddDocument(listener, thisArgs, disposables);
			},
			onDidCloseTextDocument: (listener, thisArgs?, disposables?) => {
				return extHostDocuments.onDidRemoveDocument(listener, thisArgs, disposables);
			},
			onDidChangeTextDocument: (listener, thisArgs?, disposables?) => {
				return extHostDocuments.onDidChangeDocument(listener, thisArgs, disposables);
			},
			onDidSaveTextDocument: (listener, thisArgs?, disposables?) => {
				return extHostDocuments.onDidSaveDocument(listener, thisArgs, disposables);
			},
			onWillSaveTextDocument: (listener, thisArgs?, disposables?) => {
				return extHostDocumentSaveParticipant.onWillSaveTextDocumentEvent(listener, thisArgs, disposables);
454
			},
455
			onDidChangeConfiguration: (listener: (_: any) => any, thisArgs?: any, disposables?: extHostTypes.Disposable[]) => {
456 457
				return extHostConfiguration.onDidChangeConfiguration(listener, thisArgs, disposables);
			},
S
Sandeep Somavarapu 已提交
458 459
			getConfiguration: (section?: string, resource?: vscode.Uri): vscode.WorkspaceConfiguration => {
				return extHostConfiguration.getConfiguration(section, <URI>resource);
460
			},
461 462 463
			registerTextDocumentContentProvider(scheme: string, provider: vscode.TextDocumentContentProvider) {
				return extHostDocumentContentProviders.registerTextDocumentContentProvider(scheme, provider);
			},
464
			registerTaskProvider: (type: string, provider: vscode.TaskProvider) => {
465
				return extHostTask.registerTaskProvider(extension, provider);
J
Johannes Rieken 已提交
466 467 468 469
			},
			registerFileSystemProvider: proposedApiFunction(extension, (authority, provider) => {
				return extHostWorkspace.registerFileSystemProvider(authority, provider);
			})
470
		};
471

472 473
		// namespace: scm
		const scm: typeof vscode.scm = {
474 475
			get inputBox() {
				return extHostSCM.inputBox;
476
			},
J
Joao Moreno 已提交
477
			createSourceControl(id: string, label: string) {
478 479
				telemetryService.publicLog('registerSCMProvider', {
					extensionId: extension.id,
J
Joao Moreno 已提交
480 481
					providerId: id,
					providerLabel: label
482 483
				});

J
Joao Moreno 已提交
484
				return extHostSCM.createSourceControl(id, label);
J
Joao Moreno 已提交
485
			}
486
		};
J
Joao Moreno 已提交
487

488 489
		// namespace: debug
		const debug: typeof vscode.debug = {
490 491 492
			get activeDebugSession() {
				return extHostDebugService.activeDebugSession;
			},
493
			startDebugging(folder: vscode.WorkspaceFolder | undefined, nameOrConfig: string | vscode.DebugConfiguration) {
494
				return extHostDebugService.startDebugging(folder, nameOrConfig);
495
			},
496 497
			onDidStartDebugSession(listener, thisArg?, disposables?) {
				return extHostDebugService.onDidStartDebugSession(listener, thisArg, disposables);
498 499
			},
			onDidTerminateDebugSession(listener, thisArg?, disposables?) {
500
				return extHostDebugService.onDidTerminateDebugSession(listener, thisArg, disposables);
501
			},
A
Andre Weinand 已提交
502
			onDidChangeActiveDebugSession(listener, thisArg?, disposables?) {
503
				return extHostDebugService.onDidChangeActiveDebugSession(listener, thisArg, disposables);
A
Andre Weinand 已提交
504 505
			},
			onDidReceiveDebugSessionCustomEvent(listener, thisArg?, disposables?) {
A
Andre Weinand 已提交
506
				return extHostDebugService.onDidReceiveDebugSessionCustomEvent(listener, thisArg, disposables);
507 508 509 510
			},
			registerDebugConfigurationProvider: proposedApiFunction(extension, (debugType: string, provider: vscode.DebugConfigurationProvider) => {
				return extHostDebugService.registerDebugConfigurationProvider(debugType, provider);
			}),
511 512
		};

C
Christof Marti 已提交
513
		// namespace: credentials
514
		const credentials = {
C
Christof Marti 已提交
515 516 517 518 519 520 521 522 523
			readSecret(service: string, account: string): Thenable<string | undefined> {
				return extHostCredentials.readSecret(service, account);
			},
			writeSecret(service: string, account: string, secret: string): Thenable<void> {
				return extHostCredentials.writeSecret(service, account, secret);
			},
			deleteSecret(service: string, account: string): Thenable<boolean> {
				return extHostCredentials.deleteSecret(service, account);
			}
524 525 526
		};


527
		const api: typeof vscode = {
528 529 530 531 532 533 534 535
			version: pkg.version,
			// namespaces
			commands,
			env,
			extensions,
			languages,
			window,
			workspace,
J
Joao Moreno 已提交
536
			scm,
537
			debug,
538 539 540
			// types
			CancellationTokenSource: CancellationTokenSource,
			CodeLens: extHostTypes.CodeLens,
541
			Color: extHostTypes.Color,
J
Joao Moreno 已提交
542
			ColorRange: extHostTypes.ColorRange,
543
			EndOfLine: extHostTypes.EndOfLine,
544 545 546
			CompletionItem: extHostTypes.CompletionItem,
			CompletionItemKind: extHostTypes.CompletionItemKind,
			CompletionList: extHostTypes.CompletionList,
547 548 549 550 551
			Diagnostic: extHostTypes.Diagnostic,
			DiagnosticSeverity: extHostTypes.DiagnosticSeverity,
			Disposable: extHostTypes.Disposable,
			DocumentHighlight: extHostTypes.DocumentHighlight,
			DocumentHighlightKind: extHostTypes.DocumentHighlightKind,
552
			DocumentLink: extHostTypes.DocumentLink,
553 554
			EventEmitter: Emitter,
			Hover: extHostTypes.Hover,
555
			IndentAction: languageConfiguration.IndentAction,
556
			Location: extHostTypes.Location,
557
			OverviewRulerLane: EditorCommon.OverviewRulerLane,
558 559 560 561 562 563 564 565 566 567 568 569
			ParameterInformation: extHostTypes.ParameterInformation,
			Position: extHostTypes.Position,
			Range: extHostTypes.Range,
			Selection: extHostTypes.Selection,
			SignatureHelp: extHostTypes.SignatureHelp,
			SignatureInformation: extHostTypes.SignatureInformation,
			SnippetString: extHostTypes.SnippetString,
			StatusBarAlignment: extHostTypes.StatusBarAlignment,
			SymbolInformation: extHostTypes.SymbolInformation,
			SymbolKind: extHostTypes.SymbolKind,
			TextDocumentSaveReason: extHostTypes.TextDocumentSaveReason,
			TextEdit: extHostTypes.TextEdit,
570
			TextEditorCursorStyle: TextEditorCursorStyle,
571
			TextEditorLineNumbersStyle: extHostTypes.TextEditorLineNumbersStyle,
572
			TextEditorRevealType: extHostTypes.TextEditorRevealType,
573
			TextEditorSelectionChangeKind: extHostTypes.TextEditorSelectionChangeKind,
574
			DecorationRangeBehavior: extHostTypes.DecorationRangeBehavior,
575
			Uri: <any>URI,
576 577
			ViewColumn: extHostTypes.ViewColumn,
			WorkspaceEdit: extHostTypes.WorkspaceEdit,
J
Johannes Rieken 已提交
578
			ProgressLocation: extHostTypes.ProgressLocation,
S
Sandeep Somavarapu 已提交
579
			TreeItemCollapsibleState: extHostTypes.TreeItemCollapsibleState,
S
Sandeep Somavarapu 已提交
580
			TreeItem: extHostTypes.TreeItem,
581
			ThemeColor: extHostTypes.ThemeColor,
J
Joao Moreno 已提交
582
			// functions
583
			TaskRevealKind: extHostTypes.TaskRevealKind,
584
			TaskPanelKind: extHostTypes.TaskPanelKind,
585
			TaskGroup: extHostTypes.TaskGroup,
D
Dirk Baeumer 已提交
586 587
			ProcessExecution: extHostTypes.ProcessExecution,
			ShellExecution: extHostTypes.ShellExecution,
S
Sandeep Somavarapu 已提交
588 589
			Task: extHostTypes.Task,
			ConfigurationTarget: extHostTypes.ConfigurationTarget
590
		};
591 592
		if (extension.enableProposedApi && extension.isBuiltin) {
			api['credentials'] = credentials;
593 594
		}
		return api;
595
	};
E
Erich Gamma 已提交
596 597 598 599
}

class Extension<T> implements vscode.Extension<T> {

A
Alex Dima 已提交
600
	private _extensionService: ExtHostExtensionService;
E
Erich Gamma 已提交
601 602 603 604 605

	public id: string;
	public extensionPath: string;
	public packageJSON: any;

J
Johannes Rieken 已提交
606
	constructor(extensionService: ExtHostExtensionService, description: IExtensionDescription) {
A
Alex Dima 已提交
607
		this._extensionService = extensionService;
E
Erich Gamma 已提交
608 609 610 611 612 613
		this.id = description.id;
		this.extensionPath = paths.normalize(description.extensionFolderPath, true);
		this.packageJSON = description;
	}

	get isActive(): boolean {
A
Alex Dima 已提交
614
		return this._extensionService.isActivated(this.id);
E
Erich Gamma 已提交
615 616 617
	}

	get exports(): T {
A
Alex Dima 已提交
618
		return <T>this._extensionService.getExtensionExports(this.id);
E
Erich Gamma 已提交
619 620 621
	}

	activate(): Thenable<T> {
A
Alex Dima 已提交
622
		return this._extensionService.activateById(this.id).then(() => this.exports);
E
Erich Gamma 已提交
623 624 625
	}
}

J
Johannes Rieken 已提交
626
export function initializeExtensionApi(extensionService: ExtHostExtensionService, apiFactory: IExtensionApiFactory): TPromise<void> {
627
	return extensionService.getExtensionPathIndex().then(trie => defineAPI(apiFactory, trie));
J
Johannes Rieken 已提交
628 629 630 631 632
}

function defineAPI(factory: IExtensionApiFactory, extensionPaths: TrieMap<IExtensionDescription>): void {

	// each extension is meant to get its own api implementation
J
Johannes Rieken 已提交
633
	const extApiImpl = new Map<string, typeof vscode>();
J
Johannes Rieken 已提交
634
	let defaultApiImpl: typeof vscode;
635 636 637

	const node_module = <any>require.__$__nodeRequire('module');
	const original = node_module._load;
E
Erich Gamma 已提交
638
	node_module._load = function load(request, parent, isMain) {
639 640 641 642 643
		if (request !== 'vscode') {
			return original.apply(this, arguments);
		}

		// get extension id from filename and api for extension
J
Johannes Rieken 已提交
644
		const ext = extensionPaths.findSubstr(parent.filename);
645
		if (ext) {
J
Johannes Rieken 已提交
646
			let apiImpl = extApiImpl.get(ext.id);
647
			if (!apiImpl) {
J
Johannes Rieken 已提交
648 649
				apiImpl = factory(ext);
				extApiImpl.set(ext.id, apiImpl);
650 651 652 653 654 655
			}
			return apiImpl;
		}

		// fall back to a default implementation
		if (!defaultApiImpl) {
656
			defaultApiImpl = factory(nullExtensionDescription);
E
Erich Gamma 已提交
657
		}
658
		return defaultApiImpl;
E
Erich Gamma 已提交
659 660
	};
}
661 662 663 664 665 666 667 668 669 670 671 672 673 674 675

const nullExtensionDescription: IExtensionDescription = {
	id: 'nullExtensionDescription',
	name: 'Null Extension Description',
	publisher: 'vscode',
	activationEvents: undefined,
	contributes: undefined,
	enableProposedApi: false,
	engines: undefined,
	extensionDependencies: undefined,
	extensionFolderPath: undefined,
	isBuiltin: false,
	main: undefined,
	version: undefined
};