extHost.api.impl.ts 27.8 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';

J
Johannes Rieken 已提交
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';
21
import { ExtHostTreeExplorers } from 'vs/workbench/api/node/extHostTreeExplorers';
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';
J
Joao Moreno 已提交
36
import { computeDiff } from 'vs/workbench/api/node/extHostFunctions';
37
import { ExtHostTask } from 'vs/workbench/api/node/extHostTask';
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 45 46
import { IExtensionDescription } from 'vs/platform/extensions/common/extensions';
import { ExtHostExtensionService } from 'vs/workbench/api/node/extHostExtensionService';
import { TPromise } from 'vs/base/common/winjs.base';
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
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';
E
Erich Gamma 已提交
52

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

57
function proposedApiFunction<T>(extension: IExtensionDescription, fn: T): T {
58
	if (extension.enableProposedApi) {
59 60 61 62 63 64 65 66
		return fn;
	} else {
		return <any>(() => {
			throw new Error(`${extension.id} cannot access proposed api`);
		});
	}
}

J
Joao Moreno 已提交
67
function proposed(extension: IExtensionDescription): Function {
J
Joao Moreno 已提交
68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93
	return (target: any, key: string, descriptor: any) => {
		let fnKey: string = null;
		let fn: Function = null;

		if (typeof descriptor.value === 'function') {
			fnKey = 'value';
			fn = descriptor.value;
		} else if (typeof descriptor.get === 'function') {
			fnKey = 'get';
			fn = descriptor.get;
		}

		if (!fn) {
			throw new Error('not supported');
		}

		if (extension.enableProposedApi) {
			return;
		}

		descriptor[fnKey] = () => {
			throw new Error(`${extension.id} cannot access proposed api`);
		};
	};
}

E
Erich Gamma 已提交
94
/**
95
 * This method instantiates and returns the extension API surface
E
Erich Gamma 已提交
96
 */
97
export function createApiFactory(initData: IInitData, threadService: IThreadService, extensionService: ExtHostExtensionService, contextService: IWorkspaceContextService): IExtensionApiFactory {
98

99 100
	// Addressable instances
	const col = new InstanceCollection();
101
	const extHostHeapService = col.define(ExtHostContext.ExtHostHeapService).set<ExtHostHeapService>(new ExtHostHeapService());
J
Johannes Rieken 已提交
102 103
	const extHostDocumentsAndEditors = col.define(ExtHostContext.ExtHostDocumentsAndEditors).set<ExtHostDocumentsAndEditors>(new ExtHostDocumentsAndEditors(threadService));
	const extHostDocuments = col.define(ExtHostContext.ExtHostDocuments).set<ExtHostDocuments>(new ExtHostDocuments(threadService, extHostDocumentsAndEditors));
104
	const extHostDocumentSaveParticipant = col.define(ExtHostContext.ExtHostDocumentSaveParticipant).set<ExtHostDocumentSaveParticipant>(new ExtHostDocumentSaveParticipant(extHostDocuments, threadService.get(MainContext.MainThreadWorkspace)));
J
Johannes Rieken 已提交
105
	const extHostEditors = col.define(ExtHostContext.ExtHostEditors).set<ExtHostEditors>(new ExtHostEditors(threadService, extHostDocumentsAndEditors));
106
	const extHostCommands = col.define(ExtHostContext.ExtHostCommands).set<ExtHostCommands>(new ExtHostCommands(threadService, extHostHeapService));
P
Pine Wu 已提交
107
	const extHostExplorers = col.define(ExtHostContext.ExtHostExplorers).set<ExtHostTreeExplorers>(new ExtHostTreeExplorers(threadService, extHostCommands));
108
	const extHostConfiguration = col.define(ExtHostContext.ExtHostConfiguration).set<ExtHostConfiguration>(new ExtHostConfiguration(threadService.get(MainContext.MainThreadConfiguration), initData.configuration));
109
	const extHostDiagnostics = col.define(ExtHostContext.ExtHostDiagnostics).set<ExtHostDiagnostics>(new ExtHostDiagnostics(threadService));
110
	const languageFeatures = col.define(ExtHostContext.ExtHostLanguageFeatures).set<ExtHostLanguageFeatures>(new ExtHostLanguageFeatures(threadService, extHostDocuments, extHostCommands, extHostHeapService, extHostDiagnostics));
111 112 113
	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 已提交
114
	const extHostSCM = col.define(ExtHostContext.ExtHostSCM).set<ExtHostSCM>(new ExtHostSCM(threadService));
115
	const extHostTask = col.define(ExtHostContext.ExtHostTask).set<ExtHostTask>(new ExtHostTask(threadService));
116 117
	col.define(ExtHostContext.ExtHostExtensionService).set(extensionService);
	col.finish(false, threadService);
118

119 120 121
	// Other instances
	const extHostMessageService = new ExtHostMessageService(threadService);
	const extHostStatusBar = new ExtHostStatusBar(threadService);
122
	const extHostProgress = new ExtHostProgress(threadService.get(MainContext.MainThreadProgress));
123
	const extHostOutputService = new ExtHostOutputService(threadService);
B
Benjamin Pasero 已提交
124
	const workspacePath = contextService.hasWorkspace() ? contextService.getWorkspace().resource.fsPath : undefined;
125 126
	const extHostWorkspace = new ExtHostWorkspace(threadService, workspacePath);
	const extHostLanguages = new ExtHostLanguages(threadService);
127

128 129
	// Register API-ish commands
	ExtHostApiCommands.register(extHostCommands);
130

131
	return function (extension: IExtensionDescription): typeof vscode {
132

133
		if (extension.enableProposedApi && !extension.isBuiltin) {
134

135
			if (!initData.environment.enableProposedApi) {
136 137 138 139 140 141
				extension.enableProposedApi = false;
				console.warn('PROPOSED API is only available when developing an extension');

			} else {
				console.warn(`${extension.name} (${extension.id}) uses PROPOSED API which is subject to change and removal without notice`);
			}
142 143
		}

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

					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) => {
						console.warn('An error occured while running command ' + id, err);
					});
168
				});
169 170 171 172 173 174 175 176
			},
			executeCommand<T>(id: string, ...args: any[]): Thenable<T> {
				return extHostCommands.executeCommand(id, ...args);
			},
			getCommands(filterInternal: boolean = false): Thenable<string[]> {
				return extHostCommands.getCommands(filterInternal);
			}
		};
177

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

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

200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219
		// 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 已提交
220 221
			registerImplementationProvider(selector: vscode.DocumentSelector, provider: vscode.ImplementationProvider): vscode.Disposable {
				return languageFeatures.registerImplementationProvider(selector, provider);
222
			},
223 224 225
			registerTypeDefinitionProvider(selector: vscode.DocumentSelector, provider: vscode.TypeDefinitionProvider): vscode.Disposable {
				return languageFeatures.registerTypeDefinitionProvider(selector, provider);
			},
226 227 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
			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 {
257
				return languageFeatures.registerCompletionItemProvider(selector, provider, triggerCharacters);
258 259 260 261 262 263 264 265
			},
			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 已提交
266

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

344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372
		// namespace: workspace
		const workspace: typeof vscode.workspace = {
			get rootPath() {
				return extHostWorkspace.getPath();
			},
			set rootPath(value) {
				throw errors.readonly();
			},
			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();
			},
373
			openTextDocument(uriOrFileNameOrOptions?: vscode.Uri | string | { language?: string; content?: string; }) {
B
Benjamin Pasero 已提交
374 375
				let uriPromise: TPromise<URI>;

376
				let options = uriOrFileNameOrOptions as { language?: string; content?: string; };
B
Benjamin Pasero 已提交
377 378 379 380 381 382
				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);
383
				} else {
B
Benjamin Pasero 已提交
384
					throw new Error('illegal argument - uriOrFileNameOrOptions');
385
				}
B
Benjamin Pasero 已提交
386 387 388 389 390 391

				return uriPromise.then(uri => {
					return extHostDocuments.ensureDocumentData(uri).then(() => {
						const data = extHostDocuments.getDocumentData(uri);
						return data && data.document;
					});
392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410
				});
			},
			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);
411
			},
412 413 414 415 416
			onDidChangeConfiguration: (listener: () => any, thisArgs?: any, disposables?: extHostTypes.Disposable[]) => {
				return extHostConfiguration.onDidChangeConfiguration(listener, thisArgs, disposables);
			},
			getConfiguration: (section?: string): vscode.WorkspaceConfiguration => {
				return extHostConfiguration.getConfiguration(section);
417 418 419 420
			},
			registerTaskProvider: proposedApiFunction(extension, (provider: vscode.TaskProvider) => {
				return extHostTask.registerTaskProvider(extension, provider);
			})
421
		};
422

J
Joao Moreno 已提交
423 424
		class SCM {

J
Joao Moreno 已提交
425
			@proposed(extension)
J
Joao Moreno 已提交
426 427
			get activeProvider() {
				return extHostSCM.activeProvider;
J
Joao Moreno 已提交
428
			}
J
Joao Moreno 已提交
429

J
Joao Moreno 已提交
430
			@proposed(extension)
J
Joao Moreno 已提交
431 432 433 434
			get onDidChangeActiveProvider() {
				return extHostSCM.onDidChangeActiveProvider;
			}

J
Joao Moreno 已提交
435
			@proposed(extension)
436 437 438 439 440
			get inputBox() {
				return extHostSCM.inputBox;
			}

			@proposed(extension)
J
Joao Moreno 已提交
441 442 443 444
			getResourceFromURI(uri) {
				return extHostSCM.getResourceFromURI(uri);
			}

J
Joao Moreno 已提交
445
			@proposed(extension)
J
Joao Moreno 已提交
446 447 448 449 450 451 452
			registerSCMProvider(id, provider) {
				return extHostSCM.registerSCMProvider(id, provider);
			}
		}

		// namespace: scm
		const scm: typeof vscode.scm = new SCM();
J
Joao Moreno 已提交
453

454 455 456 457 458 459 460 461 462
		return {
			version: pkg.version,
			// namespaces
			commands,
			env,
			extensions,
			languages,
			window,
			workspace,
J
Joao Moreno 已提交
463
			scm,
464 465 466 467 468 469
			// types
			CancellationTokenSource: CancellationTokenSource,
			CodeLens: extHostTypes.CodeLens,
			CompletionItem: extHostTypes.CompletionItem,
			CompletionItemKind: extHostTypes.CompletionItemKind,
			CompletionList: extHostTypes.CompletionList,
470 471 472 473 474
			Diagnostic: extHostTypes.Diagnostic,
			DiagnosticSeverity: extHostTypes.DiagnosticSeverity,
			Disposable: extHostTypes.Disposable,
			DocumentHighlight: extHostTypes.DocumentHighlight,
			DocumentHighlightKind: extHostTypes.DocumentHighlightKind,
475
			DocumentLink: extHostTypes.DocumentLink,
476 477 478
			EndOfLine: extHostTypes.EndOfLine,
			EventEmitter: Emitter,
			Hover: extHostTypes.Hover,
479
			IndentAction: languageConfiguration.IndentAction,
480
			Location: extHostTypes.Location,
481
			OverviewRulerLane: EditorCommon.OverviewRulerLane,
482 483 484 485 486 487 488 489 490 491 492 493
			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,
494 495
			TextEditorCursorStyle: EditorCommon.TextEditorCursorStyle,
			TextEditorLineNumbersStyle: extHostTypes.TextEditorLineNumbersStyle,
496
			TextEditorRevealType: extHostTypes.TextEditorRevealType,
497
			TextEditorSelectionChangeKind: extHostTypes.TextEditorSelectionChangeKind,
498 499 500
			Uri: URI,
			ViewColumn: extHostTypes.ViewColumn,
			WorkspaceEdit: extHostTypes.WorkspaceEdit,
J
Joao Moreno 已提交
501
			// functions
502 503 504 505 506 507
			computeDiff,
			FileLocationKind: extHostTypes.FileLocationKind,
			ApplyToKind: extHostTypes.ApplyToKind,
			RevealKind: extHostTypes.RevealKind,
			ShellTask: extHostTypes.ShellTask,
			ProcessTask: extHostTypes.ProcessTask
508
		};
509
	};
E
Erich Gamma 已提交
510 511 512 513
}

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

A
Alex Dima 已提交
514
	private _extensionService: ExtHostExtensionService;
E
Erich Gamma 已提交
515 516 517 518 519

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

J
Johannes Rieken 已提交
520
	constructor(extensionService: ExtHostExtensionService, description: IExtensionDescription) {
A
Alex Dima 已提交
521
		this._extensionService = extensionService;
E
Erich Gamma 已提交
522 523 524 525 526 527
		this.id = description.id;
		this.extensionPath = paths.normalize(description.extensionFolderPath, true);
		this.packageJSON = description;
	}

	get isActive(): boolean {
A
Alex Dima 已提交
528
		return this._extensionService.isActivated(this.id);
E
Erich Gamma 已提交
529 530 531
	}

	get exports(): T {
A
Alex Dima 已提交
532
		return <T>this._extensionService.get(this.id);
E
Erich Gamma 已提交
533 534 535
	}

	activate(): Thenable<T> {
A
Alex Dima 已提交
536
		return this._extensionService.activateById(this.id).then(() => this.exports);
E
Erich Gamma 已提交
537 538 539
	}
}

J
Johannes Rieken 已提交
540 541 542
export function initializeExtensionApi(extensionService: ExtHostExtensionService, apiFactory: IExtensionApiFactory): TPromise<void> {
	return createExtensionPathIndex(extensionService).then(trie => defineAPI(apiFactory, trie));
}
543

J
Johannes Rieken 已提交
544
function createExtensionPathIndex(extensionService: ExtHostExtensionService): TPromise<TrieMap<IExtensionDescription>> {
545 546

	// create trie to enable fast 'filename -> extension id' look up
547
	const trie = new TrieMap<IExtensionDescription>(TrieMap.PathSplitter);
J
Johannes Rieken 已提交
548 549
	const extensions = extensionService.getAllExtensionDescriptions().map(ext => {
		if (!ext.main) {
550
			return undefined;
551
		}
J
Johannes Rieken 已提交
552 553 554 555 556
		return new TPromise((resolve, reject) => {
			realpath(ext.extensionFolderPath, (err, path) => {
				if (err) {
					reject(err);
				} else {
J
Johannes Rieken 已提交
557
					trie.insert(path, ext);
J
Johannes Rieken 已提交
558 559 560 561 562 563 564 565 566 567 568 569
					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 已提交
570
	const extApiImpl = new Map<string, typeof vscode>();
J
Johannes Rieken 已提交
571
	let defaultApiImpl: typeof vscode;
572 573 574

	const node_module = <any>require.__$__nodeRequire('module');
	const original = node_module._load;
E
Erich Gamma 已提交
575
	node_module._load = function load(request, parent, isMain) {
576 577 578 579 580
		if (request !== 'vscode') {
			return original.apply(this, arguments);
		}

		// get extension id from filename and api for extension
J
Johannes Rieken 已提交
581
		const ext = extensionPaths.findSubstr(parent.filename);
582
		if (ext) {
J
Johannes Rieken 已提交
583
			let apiImpl = extApiImpl.get(ext.id);
584
			if (!apiImpl) {
J
Johannes Rieken 已提交
585 586
				apiImpl = factory(ext);
				extApiImpl.set(ext.id, apiImpl);
587 588 589 590 591 592
			}
			return apiImpl;
		}

		// fall back to a default implementation
		if (!defaultApiImpl) {
593
			defaultApiImpl = factory(nullExtensionDescription);
E
Erich Gamma 已提交
594
		}
595
		return defaultApiImpl;
E
Erich Gamma 已提交
596 597
	};
}
598 599 600 601 602 603 604 605 606 607 608 609 610 611 612

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