extHost.api.impl.ts 30.5 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
			},
			registerDocumentLinkProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentLinkProvider): vscode.Disposable {
				return languageFeatures.registerDocumentLinkProvider(selector, provider);
			},
264 265 266
			registerColorProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentColorProvider): vscode.Disposable {
				return languageFeatures.registerColorProvider(selector, provider);
			},
267 268 269 270
			setLanguageConfiguration: (language: string, configuration: vscode.LanguageConfiguration): vscode.Disposable => {
				return languageFeatures.setLanguageConfiguration(language, configuration);
			}
		};
E
Erich Gamma 已提交
271

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

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

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

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

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

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

467 468 469 470 471 472 473 474 475 476 477
		// namespace: debug
		const debug: typeof vscode.debug = {
			createDebugSession: proposedApiFunction(extension, (config: vscode.DebugConfiguration) => {
				return extHostDebugService.createDebugSession(config);
			}),
			onDidTerminateDebugSession: proposedApiFunction(extension, (listener, thisArg?, disposables?) => {
				return extHostDebugService.onDidTerminateDebugSession(listener, thisArg, disposables);
			})
		};


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

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

A
Alex Dima 已提交
547
	private _extensionService: ExtHostExtensionService;
E
Erich Gamma 已提交
548 549 550 551 552

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

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

	get isActive(): boolean {
A
Alex Dima 已提交
561
		return this._extensionService.isActivated(this.id);
E
Erich Gamma 已提交
562 563 564
	}

	get exports(): T {
A
Alex Dima 已提交
565
		return <T>this._extensionService.get(this.id);
E
Erich Gamma 已提交
566 567 568
	}

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

J
Johannes Rieken 已提交
573 574 575
export function initializeExtensionApi(extensionService: ExtHostExtensionService, apiFactory: IExtensionApiFactory): TPromise<void> {
	return createExtensionPathIndex(extensionService).then(trie => defineAPI(apiFactory, trie));
}
576

J
Johannes Rieken 已提交
577
function createExtensionPathIndex(extensionService: ExtHostExtensionService): TPromise<TrieMap<IExtensionDescription>> {
578 579

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

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

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

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

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