extHost.api.impl.ts 30.4 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
function proposedApiFunction<T>(extension: IExtensionDescription, fn: T): T {
59
	if (extension.enableProposedApi) {
60 61 62
		return fn;
	} else {
		return <any>(() => {
63
			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 65 66 67
		});
	}
}

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

78 79
	// Addressable instances
	const col = new InstanceCollection();
80
	const extHostHeapService = col.define(ExtHostContext.ExtHostHeapService).set<ExtHostHeapService>(new ExtHostHeapService());
81
	const extHostDebugService = col.define(ExtHostContext.ExtHostDebugService).set<ExtHostDebugService>(new ExtHostDebugService(threadService));
J
Johannes Rieken 已提交
82 83
	const extHostDocumentsAndEditors = col.define(ExtHostContext.ExtHostDocumentsAndEditors).set<ExtHostDocumentsAndEditors>(new ExtHostDocumentsAndEditors(threadService));
	const extHostDocuments = col.define(ExtHostContext.ExtHostDocuments).set<ExtHostDocuments>(new ExtHostDocuments(threadService, extHostDocumentsAndEditors));
84
	const extHostDocumentSaveParticipant = col.define(ExtHostContext.ExtHostDocumentSaveParticipant).set<ExtHostDocumentSaveParticipant>(new ExtHostDocumentSaveParticipant(extHostDocuments, threadService.get(MainContext.MainThreadWorkspace)));
J
Johannes Rieken 已提交
85
	const extHostEditors = col.define(ExtHostContext.ExtHostEditors).set<ExtHostEditors>(new ExtHostEditors(threadService, extHostDocumentsAndEditors));
86
	const extHostCommands = col.define(ExtHostContext.ExtHostCommands).set<ExtHostCommands>(new ExtHostCommands(threadService, extHostHeapService));
S
Sandeep Somavarapu 已提交
87
	const extHostTreeViews = col.define(ExtHostContext.ExtHostTreeViews).set<ExtHostTreeViews>(new ExtHostTreeViews(threadService, extHostCommands));
88
	const extHostWorkspace = col.define(ExtHostContext.ExtHostWorkspace).set<ExtHostWorkspace>(new ExtHostWorkspace(threadService, initData.workspace));
J
Johannes Rieken 已提交
89
	const extHostConfiguration = col.define(ExtHostContext.ExtHostConfiguration).set<ExtHostConfiguration>(new ExtHostConfiguration(threadService.get(MainContext.MainThreadConfiguration), extHostWorkspace, initData.configuration));
90
	const extHostDiagnostics = col.define(ExtHostContext.ExtHostDiagnostics).set<ExtHostDiagnostics>(new ExtHostDiagnostics(threadService));
91
	const languageFeatures = col.define(ExtHostContext.ExtHostLanguageFeatures).set<ExtHostLanguageFeatures>(new ExtHostLanguageFeatures(threadService, extHostDocuments, extHostCommands, extHostHeapService, extHostDiagnostics));
92 93 94
	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 已提交
95
	const extHostSCM = col.define(ExtHostContext.ExtHostSCM).set<ExtHostSCM>(new ExtHostSCM(threadService, extHostCommands));
96
	const extHostTask = col.define(ExtHostContext.ExtHostTask).set<ExtHostTask>(new ExtHostTask(threadService));
97 98
	col.define(ExtHostContext.ExtHostExtensionService).set(extensionService);
	col.finish(false, threadService);
99

100 101 102
	// Other instances
	const extHostMessageService = new ExtHostMessageService(threadService);
	const extHostStatusBar = new ExtHostStatusBar(threadService);
103
	const extHostProgress = new ExtHostProgress(threadService.get(MainContext.MainThreadProgress));
104 105
	const extHostOutputService = new ExtHostOutputService(threadService);
	const extHostLanguages = new ExtHostLanguages(threadService);
106

107 108
	// Register API-ish commands
	ExtHostApiCommands.register(extHostCommands);
109

110
	return function (extension: IExtensionDescription): typeof vscode {
111

112
		if (extension.enableProposedApi && !extension.isBuiltin) {
113

114 115 116 117
			if (
				!initData.environment.enableProposedApiForAll &&
				initData.environment.enableProposedApiFor.indexOf(extension.id) < 0
			) {
118
				extension.enableProposedApi = false;
119
				console.error(`Extension '${extension.id} cannot use PROPOSED API (must started out of dev or enabled via --enable-proposed-api)`);
120 121

			} else {
122 123 124
				// 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.`);
125
			}
126 127
		}

128 129 130 131 132 133 134 135 136 137 138 139 140 141
		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
				});
			}
		};

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

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

188 189
		// namespace: env
		const env: typeof vscode.env = Object.freeze({
190 191
			get machineId() { return initData.telemetryInfo.machineId; },
			get sessionId() { return initData.telemetryInfo.sessionId; },
192 193 194
			get language() { return Platform.language; },
			get appName() { return product.nameLong; }
		});
E
Erich Gamma 已提交
195

196 197 198
		// namespace: extensions
		const extensions: typeof vscode.extensions = {
			getExtension(extensionId: string): Extension<any> {
199
				let desc = extensionService.getExtensionDescription(extensionId);
200 201 202
				if (desc) {
					return new Extension(extensionService, desc);
				}
203
				return undefined;
204 205
			},
			get all(): Extension<any>[] {
206
				return extensionService.getAllExtensionDescriptions().map((desc) => new Extension(extensionService, desc));
E
Erich Gamma 已提交
207
			}
208
		};
E
Erich Gamma 已提交
209

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

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

355 356 357
		// namespace: workspace
		const workspace: typeof vscode.workspace = {
			get rootPath() {
358
				apiUsage.publicLog('workspace#rootPath');
359 360 361 362 363
				return extHostWorkspace.getPath();
			},
			set rootPath(value) {
				throw errors.readonly();
			},
364 365
			getWorkspaceFolder(resource) {
				return extHostWorkspace.getWorkspaceFolder(resource);
366
			},
367
			get workspaceFolders() {
368
				apiUsage.publicLog('workspace#workspaceFolders');
369
				return extHostWorkspace.getWorkspaceFolders();
370
			},
371
			onDidChangeWorkspaceFolders: function (listener, thisArgs?, disposables?) {
372
				apiUsage.publicLog('workspace#onDidChangeWorkspaceFolders');
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 395
			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();
			},
396
			openTextDocument(uriOrFileNameOrOptions?: vscode.Uri | string | { language?: string; content?: string; }) {
B
Benjamin Pasero 已提交
397 398
				let uriPromise: TPromise<URI>;

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

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

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

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

465 466
		// namespace: debug
		const debug: typeof vscode.debug = {
467 468 469
			get activeDebugSession() {
				return extHostDebugService.activeDebugSession;
			},
470 471
			startDebugSession(config: vscode.DebugConfiguration) {
				return extHostDebugService.startDebugSession(config);
472 473
			},
			onDidTerminateDebugSession(listener, thisArg?, disposables?) {
474
				return extHostDebugService.onDidTerminateDebugSession(listener, thisArg, disposables);
475
			},
A
Andre Weinand 已提交
476
			onDidChangeActiveDebugSession(listener, thisArg?, disposables?) {
477
				return extHostDebugService.onDidChangeActiveDebugSession(listener, thisArg, disposables);
A
Andre Weinand 已提交
478 479
			},
			onDidReceiveDebugSessionCustomEvent(listener, thisArg?, disposables?) {
A
Andre Weinand 已提交
480
				return extHostDebugService.onDidReceiveDebugSessionCustomEvent(listener, thisArg, disposables);
A
Andre Weinand 已提交
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
};