extHost.api.impl.ts 30.7 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';
J
Johannes Rieken 已提交
11
import { IThreadService } from 'vs/workbench/services/thread/common/threadService';
E
Erich Gamma 已提交
12
import * as errors from 'vs/base/common/errors';
13 14
import product from 'vs/platform/node/product';
import pkg from 'vs/platform/node/package';
J
Johannes Rieken 已提交
15
import { ExtHostFileSystemEventService } from 'vs/workbench/api/node/extHostFileSystemEventService';
J
Johannes Rieken 已提交
16
import { ExtHostDocumentsAndEditors } from 'vs/workbench/api/node/extHostDocumentsAndEditors';
J
Johannes Rieken 已提交
17 18 19 20
import { ExtHostDocuments } from 'vs/workbench/api/node/extHostDocuments';
import { ExtHostDocumentSaveParticipant } from 'vs/workbench/api/node/extHostDocumentSaveParticipant';
import { ExtHostConfiguration } from 'vs/workbench/api/node/extHostConfiguration';
import { ExtHostDiagnostics } from 'vs/workbench/api/node/extHostDiagnostics';
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';
J
Johannes Rieken 已提交
38
import * as extHostTypes from 'vs/workbench/api/node/extHostTypes';
E
Erich Gamma 已提交
39 40 41
import URI from 'vs/base/common/uri';
import Severity from 'vs/base/common/severity';
import EditorCommon = require('vs/editor/common/editorCommon');
J
Johannes Rieken 已提交
42 43 44
import { IExtensionDescription } from 'vs/platform/extensions/common/extensions';
import { ExtHostExtensionService } from 'vs/workbench/api/node/extHostExtensionService';
import { TPromise } from 'vs/base/common/winjs.base';
45
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
J
Johannes Rieken 已提交
46
import { CancellationTokenSource } from 'vs/base/common/cancellation';
47
import * as vscode from 'vscode';
E
Erich Gamma 已提交
48
import * as paths from 'vs/base/common/paths';
J
Johannes Rieken 已提交
49
import { realpath } from 'fs';
50
import { MainContext, ExtHostContext, InstanceCollection, IInitData } from './extHost.protocol';
51
import * as languageConfiguration from 'vs/editor/common/modes/languageConfiguration';
52
import { TextEditorCursorStyle } from 'vs/editor/common/config/editorOptions';
E
Erich Gamma 已提交
53

54
export interface IExtensionApiFactory {
55
	(extension: IExtensionDescription): typeof vscode;
56 57
}

58 59 60 61 62 63
function assertProposedApi(extension: IExtensionDescription): void {
	if (!extension.enableProposedApi) {
		throw new Error(`[${extension.id}]: Proposed API is only available when running out of dev or with the following command line switch: --enable-proposed-api ${extension.id}`);
	}
}

64
function proposedApiFunction<T>(extension: IExtensionDescription, fn: T): T {
65
	if (extension.enableProposedApi) {
66 67 68
		return fn;
	} else {
		return <any>(() => {
69
			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}`);
70 71 72 73
		});
	}
}

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

84 85
	// Addressable instances
	const col = new InstanceCollection();
86
	const extHostHeapService = col.define(ExtHostContext.ExtHostHeapService).set<ExtHostHeapService>(new ExtHostHeapService());
87
	const extHostDebugService = col.define(ExtHostContext.ExtHostDebugService).set<ExtHostDebugService>(new ExtHostDebugService(threadService));
J
Johannes Rieken 已提交
88 89
	const extHostDocumentsAndEditors = col.define(ExtHostContext.ExtHostDocumentsAndEditors).set<ExtHostDocumentsAndEditors>(new ExtHostDocumentsAndEditors(threadService));
	const extHostDocuments = col.define(ExtHostContext.ExtHostDocuments).set<ExtHostDocuments>(new ExtHostDocuments(threadService, extHostDocumentsAndEditors));
90
	const extHostDocumentSaveParticipant = col.define(ExtHostContext.ExtHostDocumentSaveParticipant).set<ExtHostDocumentSaveParticipant>(new ExtHostDocumentSaveParticipant(extHostDocuments, threadService.get(MainContext.MainThreadWorkspace)));
J
Johannes Rieken 已提交
91
	const extHostEditors = col.define(ExtHostContext.ExtHostEditors).set<ExtHostEditors>(new ExtHostEditors(threadService, extHostDocumentsAndEditors));
92
	const extHostCommands = col.define(ExtHostContext.ExtHostCommands).set<ExtHostCommands>(new ExtHostCommands(threadService, extHostHeapService));
S
Sandeep Somavarapu 已提交
93
	const extHostTreeViews = col.define(ExtHostContext.ExtHostTreeViews).set<ExtHostTreeViews>(new ExtHostTreeViews(threadService, extHostCommands));
94
	const extHostWorkspace = col.define(ExtHostContext.ExtHostWorkspace).set<ExtHostWorkspace>(new ExtHostWorkspace(threadService, initData.workspace));
J
Johannes Rieken 已提交
95
	const extHostConfiguration = col.define(ExtHostContext.ExtHostConfiguration).set<ExtHostConfiguration>(new ExtHostConfiguration(threadService.get(MainContext.MainThreadConfiguration), extHostWorkspace, initData.configuration));
96
	const extHostDiagnostics = col.define(ExtHostContext.ExtHostDiagnostics).set<ExtHostDiagnostics>(new ExtHostDiagnostics(threadService));
97
	const languageFeatures = col.define(ExtHostContext.ExtHostLanguageFeatures).set<ExtHostLanguageFeatures>(new ExtHostLanguageFeatures(threadService, extHostDocuments, extHostCommands, extHostHeapService, extHostDiagnostics));
98 99 100
	const extHostFileSystemEvent = col.define(ExtHostContext.ExtHostFileSystemEventService).set<ExtHostFileSystemEventService>(new ExtHostFileSystemEventService());
	const extHostQuickOpen = col.define(ExtHostContext.ExtHostQuickOpen).set<ExtHostQuickOpen>(new ExtHostQuickOpen(threadService));
	const extHostTerminalService = col.define(ExtHostContext.ExtHostTerminalService).set<ExtHostTerminalService>(new ExtHostTerminalService(threadService));
J
Joao Moreno 已提交
101
	const extHostSCM = col.define(ExtHostContext.ExtHostSCM).set<ExtHostSCM>(new ExtHostSCM(threadService, extHostCommands));
102
	const extHostTask = col.define(ExtHostContext.ExtHostTask).set<ExtHostTask>(new ExtHostTask(threadService));
103 104
	col.define(ExtHostContext.ExtHostExtensionService).set(extensionService);
	col.finish(false, threadService);
105

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

113 114
	// Register API-ish commands
	ExtHostApiCommands.register(extHostCommands);
115

116
	return function (extension: IExtensionDescription): typeof vscode {
117

118
		if (extension.enableProposedApi && !extension.isBuiltin) {
119

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

			} else {
128 129 130
				// 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.`);
131
			}
132 133
		}

134 135
		// namespace: commands
		const commands: typeof vscode.commands = {
136 137
			registerCommand<T>(id: string, command: <T>(...args: any[]) => T | Thenable<T>, thisArgs?: any): vscode.Disposable {
				return extHostCommands.registerCommand(id, command, thisArgs);
138
			},
139
			registerTextEditorCommand(id: string, callback: (textEditor: vscode.TextEditor, edit: vscode.TextEditorEdit, ...args: any[]) => void, thisArg?: any): vscode.Disposable {
140
				return extHostCommands.registerCommand(id, (...args: any[]): any => {
141 142 143
					let activeTextEditor = extHostEditors.getActiveTextEditor();
					if (!activeTextEditor) {
						console.warn('Cannot execute ' + id + ' because there is no active text editor.');
144
						return undefined;
145
					}
146 147 148 149 150 151 152 153 154 155

					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) => {
156
						console.warn('An error occurred while running command ' + id, err);
157
					});
158
				});
159 160
			},
			registerDiffInformationCommand: proposedApiFunction(extension, (id: string, callback: (diff: vscode.LineChange[], ...args: any[]) => any, thisArg?: any): vscode.Disposable => {
161 162 163 164 165 166 167 168 169 170
				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]);
				});
171
			}),
172
			executeCommand<T>(id: string, ...args: any[]): Thenable<T> {
173
				return extHostCommands.executeCommand<T>(id, ...args);
174
			},
175 176 177
			getCommands(filterInternal: boolean = false): Thenable<string[]> {
				return extHostCommands.getCommands(filterInternal);
			}
178
		};
179

180 181
		// namespace: env
		const env: typeof vscode.env = Object.freeze({
182 183
			get machineId() { return initData.telemetryInfo.machineId; },
			get sessionId() { return initData.telemetryInfo.sessionId; },
184 185 186
			get language() { return Platform.language; },
			get appName() { return product.nameLong; }
		});
E
Erich Gamma 已提交
187

188 189 190
		// namespace: extensions
		const extensions: typeof vscode.extensions = {
			getExtension(extensionId: string): Extension<any> {
191
				let desc = extensionService.getExtensionDescription(extensionId);
192 193 194
				if (desc) {
					return new Extension(extensionService, desc);
				}
195
				return undefined;
196 197
			},
			get all(): Extension<any>[] {
198
				return extensionService.getAllExtensionDescriptions().map((desc) => new Extension(extensionService, desc));
E
Erich Gamma 已提交
199
			}
200
		};
E
Erich Gamma 已提交
201

202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221
		// 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 已提交
222 223
			registerImplementationProvider(selector: vscode.DocumentSelector, provider: vscode.ImplementationProvider): vscode.Disposable {
				return languageFeatures.registerImplementationProvider(selector, provider);
224
			},
225 226 227
			registerTypeDefinitionProvider(selector: vscode.DocumentSelector, provider: vscode.TypeDefinitionProvider): vscode.Disposable {
				return languageFeatures.registerTypeDefinitionProvider(selector, provider);
			},
228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258
			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 {
259
				return languageFeatures.registerCompletionItemProvider(selector, provider, triggerCharacters);
260 261 262 263 264 265 266 267
			},
			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);
			}
		};
E
Erich Gamma 已提交
268

269 270 271 272 273 274 275 276
		// namespace: window
		const window: typeof vscode.window = {
			get activeTextEditor() {
				return extHostEditors.getActiveTextEditor();
			},
			get visibleTextEditors() {
				return extHostEditors.getVisibleTextEditors();
			},
277
			showTextDocument(document: vscode.TextDocument, columnOrOptions?: vscode.ViewColumn | vscode.TextDocumentShowOptions, preserveFocus?: boolean): TPromise<vscode.TextEditor> {
278
				return extHostEditors.showTextDocument(document, columnOrOptions, preserveFocus);
279 280 281 282
			},
			createTextEditorDecorationType(options: vscode.DecorationRenderOptions): vscode.TextEditorDecorationType {
				return extHostEditors.createTextEditorDecorationType(options);
			},
283 284 285
			onDidChangeActiveTextEditor(listener, thisArg?, disposables?) {
				return extHostEditors.onDidChangeActiveTextEditor(listener, thisArg, disposables);
			},
286 287 288
			onDidChangeVisibleTextEditors(listener, thisArg, disposables) {
				return extHostEditors.onDidChangeVisibleTextEditors(listener, thisArg, disposables);
			},
289
			onDidChangeTextEditorSelection(listener: (e: vscode.TextEditorSelectionChangeEvent) => any, thisArgs?: any, disposables?: extHostTypes.Disposable[]) {
290 291
				return extHostEditors.onDidChangeTextEditorSelection(listener, thisArgs, disposables);
			},
292
			onDidChangeTextEditorOptions(listener: (e: vscode.TextEditorOptionsChangeEvent) => any, thisArgs?: any, disposables?: extHostTypes.Disposable[]) {
293 294 295 296 297
				return extHostEditors.onDidChangeTextEditorOptions(listener, thisArgs, disposables);
			},
			onDidChangeTextEditorViewColumn(listener, thisArg?, disposables?) {
				return extHostEditors.onDidChangeTextEditorViewColumn(listener, thisArg, disposables);
			},
298 299 300
			onDidCloseTerminal(listener, thisArg?, disposables?) {
				return extHostTerminalService.onDidCloseTerminal(listener, thisArg, disposables);
			},
J
Joao Moreno 已提交
301 302
			showInformationMessage(message, first, ...rest) {
				return extHostMessageService.showMessage(Severity.Info, message, first, rest);
303
			},
J
Joao Moreno 已提交
304 305
			showWarningMessage(message, first, ...rest) {
				return extHostMessageService.showMessage(Severity.Warning, message, first, rest);
306
			},
J
Joao Moreno 已提交
307 308
			showErrorMessage(message, first, ...rest) {
				return extHostMessageService.showMessage(Severity.Error, message, first, rest);
309
			},
310
			showQuickPick(items: any, options: vscode.QuickPickOptions, token?: vscode.CancellationToken) {
311 312 313 314 315 316
				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 {
317
				return extHostStatusBar.createStatusBarEntry(extension.id, <number>position, priority);
318 319 320 321
			},
			setStatusBarMessage(text: string, timeoutOrThenable?: number | Thenable<any>): vscode.Disposable {
				return extHostStatusBar.setStatusBarMessage(text, timeoutOrThenable);
			},
322
			withScmProgress<R>(task: (progress: vscode.Progress<number>) => Thenable<R>) {
323
				console.warn(`[Deprecation Warning] function 'withScmProgress' is deprecated and should no longer be used. Use 'withProgress' instead.`);
324
				return extHostProgress.withProgress(extension, { location: extHostTypes.ProgressLocation.SourceControl }, (progress, token) => task({ report(n: number) { /*noop*/ } }));
J
Johannes Rieken 已提交
325 326 327
			},
			withProgress<R>(options: vscode.ProgressOptions, task: (progress: vscode.Progress<{ message?: string; percentage?: number }>) => Thenable<R>) {
				return extHostProgress.withProgress(extension, options, task);
328
			},
329 330 331
			createOutputChannel(name: string): vscode.OutputChannel {
				return extHostOutputService.createOutputChannel(name);
			},
332 333 334 335
			createTerminal(nameOrOptions: vscode.TerminalOptions | string, shellPath?: string, shellArgs?: string[]): vscode.Terminal {
				if (typeof nameOrOptions === 'object') {
					return extHostTerminalService.createTerminalFromOptions(<vscode.TerminalOptions>nameOrOptions);
				}
D
Daniel Imms 已提交
336
				return extHostTerminalService.createTerminal(<string>nameOrOptions, shellPath, shellArgs);
337
			},
S
Sandeep Somavarapu 已提交
338 339 340
			registerTreeDataProvider(viewId: string, treeDataProvider: vscode.TreeDataProvider<any>): vscode.Disposable {
				return extHostTreeViews.registerTreeDataProvider(viewId, treeDataProvider);
			},
341 342
			// proposed API
			sampleFunction: proposedApiFunction(extension, () => {
J
Joao Moreno 已提交
343
				return extHostMessageService.showMessage(Severity.Info, 'Hello Proposed Api!', {}, []);
344
			}),
345
		};
E
Erich Gamma 已提交
346

347 348 349
		// namespace: workspace
		const workspace: typeof vscode.workspace = {
			get rootPath() {
350 351 352 353
				telemetryService.publicLog('api-getter', {
					name: 'workspace#rootPath',
					extension: extension.id
				});
354 355 356 357 358
				return extHostWorkspace.getPath();
			},
			set rootPath(value) {
				throw errors.readonly();
			},
359 360
			get workspaceFolders() {
				assertProposedApi(extension);
361 362 363 364
				telemetryService.publicLog('api-getter', {
					name: 'workspace#workspaceFolders',
					extension: extension.id
				});
365 366 367
				return extHostWorkspace.getRoots();
			},
			onDidChangeWorkspaceFolders: proposedApiFunction(extension, (listener, thisArgs?, disposables?) => {
368 369 370 371
				telemetryService.publicLog('api-getter', {
					name: 'workspace#onDidChangeWorkspaceFolders',
					extension: extension.id
				});
372 373
				return extHostWorkspace.onDidChangeWorkspace(listener, thisArgs, disposables);
			}),
374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394
			asRelativePath: (pathOrUri) => {
				return extHostWorkspace.getRelativePath(pathOrUri);
			},
			findFiles: (include, exclude, maxResults?, token?) => {
				return extHostWorkspace.findFiles(include, exclude, maxResults, token);
			},
			saveAll: (includeUntitled?) => {
				return extHostWorkspace.saveAll(includeUntitled);
			},
			applyEdit(edit: vscode.WorkspaceEdit): TPromise<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();
			},
395
			openTextDocument(uriOrFileNameOrOptions?: vscode.Uri | string | { language?: string; content?: string; }) {
B
Benjamin Pasero 已提交
396 397
				let uriPromise: TPromise<URI>;

398
				let options = uriOrFileNameOrOptions as { language?: string; content?: string; };
B
Benjamin Pasero 已提交
399 400 401 402 403 404
				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);
405
				} else {
B
Benjamin Pasero 已提交
406
					throw new Error('illegal argument - uriOrFileNameOrOptions');
407
				}
B
Benjamin Pasero 已提交
408 409 410 411 412 413

				return uriPromise.then(uri => {
					return extHostDocuments.ensureDocumentData(uri).then(() => {
						const data = extHostDocuments.getDocumentData(uri);
						return data && data.document;
					});
414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432
				});
			},
			registerTextDocumentContentProvider(scheme: string, provider: vscode.TextDocumentContentProvider) {
				return extHostDocuments.registerTextDocumentContentProvider(scheme, provider);
			},
			onDidOpenTextDocument: (listener, thisArgs?, disposables?) => {
				return extHostDocuments.onDidAddDocument(listener, thisArgs, disposables);
			},
			onDidCloseTextDocument: (listener, thisArgs?, disposables?) => {
				return extHostDocuments.onDidRemoveDocument(listener, thisArgs, disposables);
			},
			onDidChangeTextDocument: (listener, thisArgs?, disposables?) => {
				return extHostDocuments.onDidChangeDocument(listener, thisArgs, disposables);
			},
			onDidSaveTextDocument: (listener, thisArgs?, disposables?) => {
				return extHostDocuments.onDidSaveDocument(listener, thisArgs, disposables);
			},
			onWillSaveTextDocument: (listener, thisArgs?, disposables?) => {
				return extHostDocumentSaveParticipant.onWillSaveTextDocumentEvent(listener, thisArgs, disposables);
433
			},
434
			onDidChangeConfiguration: (listener: (_: any) => any, thisArgs?: any, disposables?: extHostTypes.Disposable[]) => {
435 436 437 438
				return extHostConfiguration.onDidChangeConfiguration(listener, thisArgs, disposables);
			},
			getConfiguration: (section?: string): vscode.WorkspaceConfiguration => {
				return extHostConfiguration.getConfiguration(section);
439
			},
440
			getConfiguration2: proposedApiFunction(extension, (section?: string, resource?: vscode.Uri): vscode.WorkspaceConfiguration => {
S
Sandeep Somavarapu 已提交
441
				return extHostConfiguration.getConfiguration2(section, <URI>resource);
442
			}),
443
			registerTaskProvider: (type: string, provider: vscode.TaskProvider) => {
444
				return extHostTask.registerTaskProvider(extension, provider);
445
			}
446
		};
447

448 449
		// namespace: scm
		const scm: typeof vscode.scm = {
450 451
			get inputBox() {
				return extHostSCM.inputBox;
452
			},
J
Joao Moreno 已提交
453
			createSourceControl(id: string, label: string) {
454 455
				telemetryService.publicLog('registerSCMProvider', {
					extensionId: extension.id,
J
Joao Moreno 已提交
456 457
					providerId: id,
					providerLabel: label
458 459
				});

J
Joao Moreno 已提交
460
				return extHostSCM.createSourceControl(id, label);
J
Joao Moreno 已提交
461
			}
462
		};
J
Joao Moreno 已提交
463

464 465
		// namespace: debug
		const debug: typeof vscode.debug = {
466 467 468 469
			get activeDebugSession() {
				assertProposedApi(extension);
				return extHostDebugService.activeDebugSession;
			},
470
			createDebugSession(config: vscode.DebugConfiguration) {
471
				return extHostDebugService.createDebugSession(config);
472 473
			},
			onDidTerminateDebugSession(listener, thisArg?, disposables?) {
474
				return extHostDebugService.onDidTerminateDebugSession(listener, thisArg, disposables);
475 476 477
			},
			onDidChangeActiveDebugSession: proposedApiFunction(extension, (listener, thisArg?, disposables?) => {
				return extHostDebugService.onDidChangeActiveDebugSession(listener, thisArg, disposables);
A
Andre Weinand 已提交
478 479 480
			}),
			onDidReceiveDebugSessionCustomEvent: proposedApiFunction(extension, (listener, thisArg?, disposables?) => {
				return extHostDebugService.onDidReceiveDebugSessionCustomEvent(listener, thisArg, disposables);
481
			})
482 483 484
		};


485 486 487 488 489 490 491 492 493
		return {
			version: pkg.version,
			// namespaces
			commands,
			env,
			extensions,
			languages,
			window,
			workspace,
J
Joao Moreno 已提交
494
			scm,
495
			debug,
496 497 498 499 500 501
			// types
			CancellationTokenSource: CancellationTokenSource,
			CodeLens: extHostTypes.CodeLens,
			CompletionItem: extHostTypes.CompletionItem,
			CompletionItemKind: extHostTypes.CompletionItemKind,
			CompletionList: extHostTypes.CompletionList,
502 503 504 505 506
			Diagnostic: extHostTypes.Diagnostic,
			DiagnosticSeverity: extHostTypes.DiagnosticSeverity,
			Disposable: extHostTypes.Disposable,
			DocumentHighlight: extHostTypes.DocumentHighlight,
			DocumentHighlightKind: extHostTypes.DocumentHighlightKind,
507
			DocumentLink: extHostTypes.DocumentLink,
508 509 510
			EndOfLine: extHostTypes.EndOfLine,
			EventEmitter: Emitter,
			Hover: extHostTypes.Hover,
511
			IndentAction: languageConfiguration.IndentAction,
512
			Location: extHostTypes.Location,
513
			OverviewRulerLane: EditorCommon.OverviewRulerLane,
514 515 516 517 518 519 520 521 522 523 524 525
			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,
526
			TextEditorCursorStyle: TextEditorCursorStyle,
527
			TextEditorLineNumbersStyle: extHostTypes.TextEditorLineNumbersStyle,
528
			TextEditorRevealType: extHostTypes.TextEditorRevealType,
529
			TextEditorSelectionChangeKind: extHostTypes.TextEditorSelectionChangeKind,
530
			DecorationRangeBehavior: extHostTypes.DecorationRangeBehavior,
531 532 533
			Uri: URI,
			ViewColumn: extHostTypes.ViewColumn,
			WorkspaceEdit: extHostTypes.WorkspaceEdit,
J
Johannes Rieken 已提交
534
			ProgressLocation: extHostTypes.ProgressLocation,
S
Sandeep Somavarapu 已提交
535
			TreeItemCollapsibleState: extHostTypes.TreeItemCollapsibleState,
S
Sandeep Somavarapu 已提交
536
			TreeItem: extHostTypes.TreeItem,
537
			ThemeColor: extHostTypes.ThemeColor,
J
Joao Moreno 已提交
538
			// functions
539
			TaskRevealKind: extHostTypes.TaskRevealKind,
540
			TaskPanelKind: extHostTypes.TaskPanelKind,
541
			TaskGroup: extHostTypes.TaskGroup,
D
Dirk Baeumer 已提交
542 543 544
			ProcessExecution: extHostTypes.ProcessExecution,
			ShellExecution: extHostTypes.ShellExecution,
			Task: extHostTypes.Task
545
		};
546
	};
E
Erich Gamma 已提交
547 548 549 550
}

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

A
Alex Dima 已提交
551
	private _extensionService: ExtHostExtensionService;
E
Erich Gamma 已提交
552 553 554 555 556

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

J
Johannes Rieken 已提交
557
	constructor(extensionService: ExtHostExtensionService, description: IExtensionDescription) {
A
Alex Dima 已提交
558
		this._extensionService = extensionService;
E
Erich Gamma 已提交
559 560 561 562 563 564
		this.id = description.id;
		this.extensionPath = paths.normalize(description.extensionFolderPath, true);
		this.packageJSON = description;
	}

	get isActive(): boolean {
A
Alex Dima 已提交
565
		return this._extensionService.isActivated(this.id);
E
Erich Gamma 已提交
566 567 568
	}

	get exports(): T {
A
Alex Dima 已提交
569
		return <T>this._extensionService.get(this.id);
E
Erich Gamma 已提交
570 571 572
	}

	activate(): Thenable<T> {
A
Alex Dima 已提交
573
		return this._extensionService.activateById(this.id).then(() => this.exports);
E
Erich Gamma 已提交
574 575 576
	}
}

J
Johannes Rieken 已提交
577 578 579
export function initializeExtensionApi(extensionService: ExtHostExtensionService, apiFactory: IExtensionApiFactory): TPromise<void> {
	return createExtensionPathIndex(extensionService).then(trie => defineAPI(apiFactory, trie));
}
580

J
Johannes Rieken 已提交
581
function createExtensionPathIndex(extensionService: ExtHostExtensionService): TPromise<TrieMap<IExtensionDescription>> {
582 583

	// create trie to enable fast 'filename -> extension id' look up
584
	const trie = new TrieMap<IExtensionDescription>(TrieMap.PathSplitter);
J
Johannes Rieken 已提交
585 586
	const extensions = extensionService.getAllExtensionDescriptions().map(ext => {
		if (!ext.main) {
587
			return undefined;
588
		}
J
Johannes Rieken 已提交
589 590 591 592 593
		return new TPromise((resolve, reject) => {
			realpath(ext.extensionFolderPath, (err, path) => {
				if (err) {
					reject(err);
				} else {
J
Johannes Rieken 已提交
594
					trie.insert(path, ext);
J
Johannes Rieken 已提交
595 596 597 598 599 600 601 602 603 604 605 606
					resolve(void 0);
				}
			});
		});
	});

	return TPromise.join(extensions).then(() => trie);
}

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

	// each extension is meant to get its own api implementation
J
Johannes Rieken 已提交
607
	const extApiImpl = new Map<string, typeof vscode>();
J
Johannes Rieken 已提交
608
	let defaultApiImpl: typeof vscode;
609 610 611

	const node_module = <any>require.__$__nodeRequire('module');
	const original = node_module._load;
E
Erich Gamma 已提交
612
	node_module._load = function load(request, parent, isMain) {
613 614 615 616 617
		if (request !== 'vscode') {
			return original.apply(this, arguments);
		}

		// get extension id from filename and api for extension
J
Johannes Rieken 已提交
618
		const ext = extensionPaths.findSubstr(parent.filename);
619
		if (ext) {
J
Johannes Rieken 已提交
620
			let apiImpl = extApiImpl.get(ext.id);
621
			if (!apiImpl) {
J
Johannes Rieken 已提交
622 623
				apiImpl = factory(ext);
				extApiImpl.set(ext.id, apiImpl);
624 625 626 627 628 629
			}
			return apiImpl;
		}

		// fall back to a default implementation
		if (!defaultApiImpl) {
630
			defaultApiImpl = factory(nullExtensionDescription);
E
Erich Gamma 已提交
631
		}
632
		return defaultApiImpl;
E
Erich Gamma 已提交
633 634
	};
}
635 636 637 638 639 640 641 642 643 644 645 646 647 648 649

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
};