extHost.api.impl.ts 30.1 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
			createDebugSession(config: vscode.DebugConfiguration) {
467
				return extHostDebugService.createDebugSession(config);
468 469
			},
			onDidTerminateDebugSession(listener, thisArg?, disposables?) {
470
				return extHostDebugService.onDidTerminateDebugSession(listener, thisArg, disposables);
471
			}
472 473 474
		};


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

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

A
Alex Dima 已提交
541
	private _extensionService: ExtHostExtensionService;
E
Erich Gamma 已提交
542 543 544 545 546

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

J
Johannes Rieken 已提交
547
	constructor(extensionService: ExtHostExtensionService, description: IExtensionDescription) {
A
Alex Dima 已提交
548
		this._extensionService = extensionService;
E
Erich Gamma 已提交
549 550 551 552 553 554
		this.id = description.id;
		this.extensionPath = paths.normalize(description.extensionFolderPath, true);
		this.packageJSON = description;
	}

	get isActive(): boolean {
A
Alex Dima 已提交
555
		return this._extensionService.isActivated(this.id);
E
Erich Gamma 已提交
556 557 558
	}

	get exports(): T {
A
Alex Dima 已提交
559
		return <T>this._extensionService.get(this.id);
E
Erich Gamma 已提交
560 561 562
	}

	activate(): Thenable<T> {
A
Alex Dima 已提交
563
		return this._extensionService.activateById(this.id).then(() => this.exports);
E
Erich Gamma 已提交
564 565 566
	}
}

J
Johannes Rieken 已提交
567 568 569
export function initializeExtensionApi(extensionService: ExtHostExtensionService, apiFactory: IExtensionApiFactory): TPromise<void> {
	return createExtensionPathIndex(extensionService).then(trie => defineAPI(apiFactory, trie));
}
570

J
Johannes Rieken 已提交
571
function createExtensionPathIndex(extensionService: ExtHostExtensionService): TPromise<TrieMap<IExtensionDescription>> {
572 573

	// create trie to enable fast 'filename -> extension id' look up
574
	const trie = new TrieMap<IExtensionDescription>(TrieMap.PathSplitter);
J
Johannes Rieken 已提交
575 576
	const extensions = extensionService.getAllExtensionDescriptions().map(ext => {
		if (!ext.main) {
577
			return undefined;
578
		}
J
Johannes Rieken 已提交
579 580 581 582 583
		return new TPromise((resolve, reject) => {
			realpath(ext.extensionFolderPath, (err, path) => {
				if (err) {
					reject(err);
				} else {
J
Johannes Rieken 已提交
584
					trie.insert(path, ext);
J
Johannes Rieken 已提交
585 586 587 588 589 590 591 592 593 594 595 596
					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 已提交
597
	const extApiImpl = new Map<string, typeof vscode>();
J
Johannes Rieken 已提交
598
	let defaultApiImpl: typeof vscode;
599 600 601

	const node_module = <any>require.__$__nodeRequire('module');
	const original = node_module._load;
E
Erich Gamma 已提交
602
	node_module._load = function load(request, parent, isMain) {
603 604 605 606 607
		if (request !== 'vscode') {
			return original.apply(this, arguments);
		}

		// get extension id from filename and api for extension
J
Johannes Rieken 已提交
608
		const ext = extensionPaths.findSubstr(parent.filename);
609
		if (ext) {
J
Johannes Rieken 已提交
610
			let apiImpl = extApiImpl.get(ext.id);
611
			if (!apiImpl) {
J
Johannes Rieken 已提交
612 613
				apiImpl = factory(ext);
				extApiImpl.set(ext.id, apiImpl);
614 615 616 617 618 619
			}
			return apiImpl;
		}

		// fall back to a default implementation
		if (!defaultApiImpl) {
620
			defaultApiImpl = factory(nullExtensionDescription);
E
Erich Gamma 已提交
621
		}
622
		return defaultApiImpl;
E
Erich Gamma 已提交
623 624
	};
}
625 626 627 628 629 630 631 632 633 634 635 636 637 638 639

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