extHostLanguageFeatures.ts 36.1 KB
Newer Older
J
Johannes Rieken 已提交
1 2 3 4 5 6 7 8
/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/
'use strict';

import URI from 'vs/base/common/uri';
import {TPromise} from 'vs/base/common/winjs.base';
J
Joao Moreno 已提交
9
import {IDisposable, dispose} from 'vs/base/common/lifecycle';
J
Johannes Rieken 已提交
10 11
import {Remotable, IThreadService} from 'vs/platform/thread/common/thread';
import * as vscode from 'vscode';
J
Johannes Rieken 已提交
12
import * as TypeConverters from 'vs/workbench/api/node/extHostTypeConverters';
13
import {Range, DocumentHighlightKind, Disposable, SignatureHelp, CompletionList} from 'vs/workbench/api/node/extHostTypes';
14
import {IReadOnlyModel, IEditorPosition, IPosition, IRange, ISingleEditOperation} from 'vs/editor/common/editorCommon';
J
Johannes Rieken 已提交
15
import * as modes from 'vs/editor/common/modes';
J
Johannes Rieken 已提交
16 17
import {ExtHostModelService} from 'vs/workbench/api/node/extHostDocuments';
import {ExtHostCommands} from 'vs/workbench/api/node/extHostCommands';
18
import {ExtHostDiagnostics} from 'vs/workbench/api/node/extHostDiagnostics';
B
Benjamin Pasero 已提交
19
import {NavigateTypesSupportRegistry, INavigateTypesSupport, ITypeBearing} from 'vs/workbench/parts/search/common/search';
20 21
import {asWinJsPromise, ShallowCancelThenPromise, wireCancellationToken} from 'vs/base/common/async';
import {CancellationToken} from 'vs/base/common/cancellation';
J
Johannes Rieken 已提交
22 23 24

// --- adapter

25
class OutlineAdapter implements modes.IOutlineSupport {
J
Johannes Rieken 已提交
26

27
	private _documents: ExtHostModelService;
J
Johannes Rieken 已提交
28 29
	private _provider: vscode.DocumentSymbolProvider;

30
	constructor(documents: ExtHostModelService, provider: vscode.DocumentSymbolProvider) {
J
Johannes Rieken 已提交
31 32 33 34
		this._documents = documents;
		this._provider = provider;
	}

35
	getOutline(resource: URI): TPromise<modes.IOutlineEntry[]> {
36
		let doc = this._documents.getDocumentData(resource).document;
J
Johannes Rieken 已提交
37 38
		return asWinJsPromise(token => this._provider.provideDocumentSymbols(doc, token)).then(value => {
			if (Array.isArray(value)) {
39
				return value.map(TypeConverters.SymbolInformation.toOutlineEntry);
J
Johannes Rieken 已提交
40 41 42 43 44
			}
		});
	}
}

45 46 47 48
interface CachedCodeLens {
	symbols: modes.ICodeLensSymbol[];
	lenses: vscode.CodeLens[];
	disposables: IDisposable[];
J
Johannes Rieken 已提交
49
}
50

51 52
class CodeLensAdapter implements modes.ICodeLensSupport {

53
	private _documents: ExtHostModelService;
54
	private _commands: ExtHostCommands;
55 56
	private _provider: vscode.CodeLensProvider;

57
	private _cache: { [uri: string]: { version: number; data: TPromise<CachedCodeLens>; } } = Object.create(null);
58

59
	constructor(documents: ExtHostModelService, commands: ExtHostCommands, provider: vscode.CodeLensProvider) {
60
		this._documents = documents;
61
		this._commands = commands;
62 63 64 65
		this._provider = provider;
	}

	findCodeLensSymbols(resource: URI): TPromise<modes.ICodeLensSymbol[]> {
66
		const doc = this._documents.getDocumentData(resource).document;
67 68
		const version = doc.version;
		const key = resource.toString();
69

70
		// from cache
71
		let entry = this._cache[key];
72
		if (entry && entry.version === version) {
73
			return new ShallowCancelThenPromise(entry.data.then(cached => cached.symbols));
74
		}
75

76 77
		const newCodeLensData = asWinJsPromise(token => this._provider.provideCodeLenses(doc, token)).then(lenses => {
			if (!Array.isArray(lenses)) {
78 79 80
				return;
			}

81 82 83 84
			const data: CachedCodeLens = {
				lenses,
				symbols: [],
				disposables: [],
J
Johannes Rieken 已提交
85
			};
86

87 88
			lenses.forEach((lens, i) => {
				data.symbols.push(<modes.ICodeLensSymbol>{
89
					id: String(i),
J
Johannes Rieken 已提交
90
					range: TypeConverters.fromRange(lens.range),
91
					command: TypeConverters.Command.from(lens.command, data.disposables)
92
				});
93
			});
94 95 96 97 98 99 100 101 102

			return data;
		});

		this._cache[key] = {
			version,
			data: newCodeLensData
		};

103
		return new ShallowCancelThenPromise(newCodeLensData.then(newCached => {
104 105
			if (entry) {
				// only now dispose old commands et al
J
Joao Moreno 已提交
106
				entry.data.then(oldCached => dispose(oldCached.disposables));
107 108
			}
			return newCached && newCached.symbols;
109
		}));
110

111 112
	}

J
Johannes Rieken 已提交
113
	resolveCodeLensSymbol(resource: URI, symbol: modes.ICodeLensSymbol): TPromise<modes.ICodeLensSymbol> {
114

115 116
		const entry = this._cache[resource.toString()];
		if (!entry) {
117 118 119
			return;
		}

120
		return entry.data.then(cachedData => {
121

122 123 124
			if (!cachedData) {
				return;
			}
125

126 127 128 129 130 131 132 133 134 135
			let lens = cachedData.lenses[Number(symbol.id)];
			if (!lens) {
				return;
			}

			let resolve: TPromise<vscode.CodeLens>;
			if (typeof this._provider.resolveCodeLens !== 'function' || lens.isResolved) {
				resolve = TPromise.as(lens);
			} else {
				resolve = asWinJsPromise(token => this._provider.resolveCodeLens(lens, token));
136
			}
J
Johannes Rieken 已提交
137

138 139 140 141 142 143 144 145 146 147
			return resolve.then(newLens => {
				lens = newLens || lens;
				let command = lens.command;
				if (!command) {
					command = {
						title: '<<MISSING COMMAND>>',
						command: 'missing',
					};
				}

148
				symbol.command = TypeConverters.Command.from(command, cachedData.disposables);
149 150
				return symbol;
			});
151 152 153 154
		});
	}
}

J
Johannes Rieken 已提交
155 156
class DeclarationAdapter implements modes.IDeclarationSupport {

157
	private _documents: ExtHostModelService;
J
Johannes Rieken 已提交
158 159
	private _provider: vscode.DefinitionProvider;

160
	constructor(documents: ExtHostModelService, provider: vscode.DefinitionProvider) {
J
Johannes Rieken 已提交
161 162 163 164 165
		this._documents = documents;
		this._provider = provider;
	}

	findDeclaration(resource: URI, position: IPosition): TPromise<modes.IReference[]> {
166
		let doc = this._documents.getDocumentData(resource).document;
J
Johannes Rieken 已提交
167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187
		let pos = TypeConverters.toPosition(position);
		return asWinJsPromise(token => this._provider.provideDefinition(doc, pos, token)).then(value => {
			if (Array.isArray(value)) {
				return value.map(DeclarationAdapter._convertLocation);
			} else if (value) {
				return DeclarationAdapter._convertLocation(value);
			}
		});
	}

	private static _convertLocation(location: vscode.Location): modes.IReference {
		if (!location) {
			return;
		}
		return <modes.IReference>{
			resource: location.uri,
			range: TypeConverters.fromRange(location.range)
		};
	}
}

A
Alex Dima 已提交
188
class HoverProviderAdapter {
J
Johannes Rieken 已提交
189

190
	private _documents: ExtHostModelService;
J
Johannes Rieken 已提交
191 192
	private _provider: vscode.HoverProvider;

193
	constructor(documents: ExtHostModelService, provider: vscode.HoverProvider) {
J
Johannes Rieken 已提交
194 195 196 197
		this._documents = documents;
		this._provider = provider;
	}

198
	public provideHover(resource: URI, position: IPosition): TPromise<modes.Hover> {
J
Johannes Rieken 已提交
199

200
		let doc = this._documents.getDocumentData(resource).document;
J
Johannes Rieken 已提交
201 202 203 204 205 206
		let pos = TypeConverters.toPosition(position);

		return asWinJsPromise(token => this._provider.provideHover(doc, pos, token)).then(value => {
			if (!value) {
				return;
			}
207 208
			if (!value.range) {
				value.range = doc.getWordRangeAtPosition(pos);
J
Johannes Rieken 已提交
209
			}
210 211
			if (!value.range) {
				value.range = new Range(pos, pos);
J
Johannes Rieken 已提交
212 213
			}

214
			return TypeConverters.fromHover(value);
J
Johannes Rieken 已提交
215 216 217 218
		});
	}
}

219 220
class OccurrencesAdapter implements modes.IOccurrencesSupport {

221
	private _documents: ExtHostModelService;
222 223
	private _provider: vscode.DocumentHighlightProvider;

224
	constructor(documents: ExtHostModelService, provider: vscode.DocumentHighlightProvider) {
225 226 227 228 229 230
		this._documents = documents;
		this._provider = provider;
	}

	findOccurrences(resource: URI, position: IPosition): TPromise<modes.IOccurence[]> {

231
		let doc = this._documents.getDocumentData(resource).document;
232 233 234 235 236 237 238 239 240 241 242 243 244
		let pos = TypeConverters.toPosition(position);

		return asWinJsPromise(token => this._provider.provideDocumentHighlights(doc, pos, token)).then(value => {
			if (Array.isArray(value)) {
				return value.map(OccurrencesAdapter._convertDocumentHighlight);
			}
		});
	}

	private static _convertDocumentHighlight(documentHighlight: vscode.DocumentHighlight): modes.IOccurence {
		return {
			range: TypeConverters.fromRange(documentHighlight.range),
			kind: DocumentHighlightKind[documentHighlight.kind].toString().toLowerCase()
B
Benjamin Pasero 已提交
245
		};
246 247 248
	}
}

J
Johannes Rieken 已提交
249 250
class ReferenceAdapter implements modes.IReferenceSupport {

251
	private _documents: ExtHostModelService;
J
Johannes Rieken 已提交
252 253
	private _provider: vscode.ReferenceProvider;

254
	constructor(documents: ExtHostModelService, provider: vscode.ReferenceProvider) {
J
Johannes Rieken 已提交
255 256 257 258 259
		this._documents = documents;
		this._provider = provider;
	}

	findReferences(resource: URI, position: IPosition, includeDeclaration: boolean): TPromise<modes.IReference[]> {
260
		let doc = this._documents.getDocumentData(resource).document;
J
Johannes Rieken 已提交
261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277
		let pos = TypeConverters.toPosition(position);

		return asWinJsPromise(token => this._provider.provideReferences(doc, pos, { includeDeclaration }, token)).then(value => {
			if (Array.isArray(value)) {
				return value.map(ReferenceAdapter._convertLocation);
			}
		});
	}

	private static _convertLocation(location: vscode.Location): modes.IReference {
		return <modes.IReference>{
			resource: location.uri,
			range: TypeConverters.fromRange(location.range)
		};
	}
}

J
Johannes Rieken 已提交
278 279
class QuickFixAdapter implements modes.IQuickFixSupport {

280 281
	private _documents: ExtHostModelService;
	private _commands: ExtHostCommands;
282
	private _diagnostics: ExtHostDiagnostics;
J
Johannes Rieken 已提交
283 284
	private _provider: vscode.CodeActionProvider;

285 286
	private _cachedCommands: IDisposable[] = [];

287
	constructor(documents: ExtHostModelService, commands: ExtHostCommands, diagnostics: ExtHostDiagnostics, provider: vscode.CodeActionProvider) {
J
Johannes Rieken 已提交
288 289
		this._documents = documents;
		this._commands = commands;
290
		this._diagnostics = diagnostics;
J
Johannes Rieken 已提交
291 292 293
		this._provider = provider;
	}

294
	getQuickFixes(resource: URI, range: IRange): TPromise<modes.IQuickFix[]> {
J
Johannes Rieken 已提交
295

296
		const doc = this._documents.getDocumentData(resource).document;
J
Johannes Rieken 已提交
297
		const ran = TypeConverters.toRange(range);
298 299 300 301 302 303 304 305 306 307
		const allDiagnostics: vscode.Diagnostic[] = [];

		this._diagnostics.forEach(collection => {
			if (collection.has(resource)) {
				for (let diagnostic of collection.get(resource)) {
					if (diagnostic.range.intersection(ran)) {
						allDiagnostics.push(diagnostic);
					}
				}
			}
J
Johannes Rieken 已提交
308 309
		});

J
Joao Moreno 已提交
310
		this._cachedCommands = dispose(this._cachedCommands);
311

312
		return asWinJsPromise(token => this._provider.provideCodeActions(doc, ran, { diagnostics: allDiagnostics }, token)).then(commands => {
J
Johannes Rieken 已提交
313 314 315 316 317
			if (!Array.isArray(commands)) {
				return;
			}
			return commands.map((command, i) => {
				return <modes.IQuickFix> {
318
					command: TypeConverters.Command.from(command, this._cachedCommands),
319
					score: i
J
Johannes Rieken 已提交
320 321 322 323 324
				};
			});
		});
	}

325
	runQuickFixAction(resource: URI, range: IRange, quickFix: modes.IQuickFix): any {
326 327
		let command = TypeConverters.Command.to(quickFix.command);
		return this._commands.executeCommand(command.command, ...command.arguments);
J
Johannes Rieken 已提交
328 329 330
	}
}

331 332
class DocumentFormattingAdapter implements modes.IFormattingSupport {

333
	private _documents: ExtHostModelService;
334 335
	private _provider: vscode.DocumentFormattingEditProvider;

336
	constructor(documents: ExtHostModelService, provider: vscode.DocumentFormattingEditProvider) {
337 338 339 340 341 342
		this._documents = documents;
		this._provider = provider;
	}

	formatDocument(resource: URI, options: modes.IFormattingOptions): TPromise<ISingleEditOperation[]> {

343
		let doc = this._documents.getDocumentData(resource).document;
344 345 346

		return asWinJsPromise(token => this._provider.provideDocumentFormattingEdits(doc, <any>options, token)).then(value => {
			if (Array.isArray(value)) {
347
				return value.map(TypeConverters.TextEdit.from);
348 349 350 351 352 353 354
			}
		});
	}
}

class RangeFormattingAdapter implements modes.IFormattingSupport {

355
	private _documents: ExtHostModelService;
356 357
	private _provider: vscode.DocumentRangeFormattingEditProvider;

358
	constructor(documents: ExtHostModelService, provider: vscode.DocumentRangeFormattingEditProvider) {
359 360 361 362 363 364
		this._documents = documents;
		this._provider = provider;
	}

	formatRange(resource: URI, range: IRange, options: modes.IFormattingOptions): TPromise<ISingleEditOperation[]> {

365
		let doc = this._documents.getDocumentData(resource).document;
366 367 368 369
		let ran = TypeConverters.toRange(range);

		return asWinJsPromise(token => this._provider.provideDocumentRangeFormattingEdits(doc, ran, <any>options, token)).then(value => {
			if (Array.isArray(value)) {
370
				return value.map(TypeConverters.TextEdit.from);
371 372 373 374 375 376 377
			}
		});
	}
}

class OnTypeFormattingAdapter implements modes.IFormattingSupport {

378
	private _documents: ExtHostModelService;
379 380
	private _provider: vscode.OnTypeFormattingEditProvider;

381
	constructor(documents: ExtHostModelService, provider: vscode.OnTypeFormattingEditProvider) {
382 383 384 385
		this._documents = documents;
		this._provider = provider;
	}

386
	autoFormatTriggerCharacters: string[] = []; // not here
387 388 389

	formatAfterKeystroke(resource: URI, position: IPosition, ch: string, options: modes.IFormattingOptions): TPromise<ISingleEditOperation[]> {

390
		let doc = this._documents.getDocumentData(resource).document;
391 392 393 394
		let pos = TypeConverters.toPosition(position);

		return asWinJsPromise(token => this._provider.provideOnTypeFormattingEdits(doc, pos, ch, <any> options, token)).then(value => {
			if (Array.isArray(value)) {
395
				return value.map(TypeConverters.TextEdit.from);
396 397 398 399 400
			}
		});
	}
}

401 402 403 404 405 406 407 408 409 410 411
class NavigateTypeAdapter implements INavigateTypesSupport {

	private _provider: vscode.WorkspaceSymbolProvider;

	constructor(provider: vscode.WorkspaceSymbolProvider) {
		this._provider = provider;
	}

	getNavigateToItems(search: string): TPromise<ITypeBearing[]> {
		return asWinJsPromise(token => this._provider.provideWorkspaceSymbols(search, token)).then(value => {
			if (Array.isArray(value)) {
412
				return value.map(TypeConverters.fromSymbolInformation);
413 414 415 416 417
			}
		});
	}
}

J
Johannes Rieken 已提交
418 419
class RenameAdapter implements modes.IRenameSupport {

420
	private _documents: ExtHostModelService;
J
Johannes Rieken 已提交
421 422
	private _provider: vscode.RenameProvider;

423
	constructor(documents: ExtHostModelService, provider: vscode.RenameProvider) {
J
Johannes Rieken 已提交
424 425 426 427 428 429
		this._documents = documents;
		this._provider = provider;
	}

	rename(resource: URI, position: IPosition, newName: string): TPromise<modes.IRenameResult> {

430
		let doc = this._documents.getDocumentData(resource).document;
J
Johannes Rieken 已提交
431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467
		let pos = TypeConverters.toPosition(position);

		return asWinJsPromise(token => this._provider.provideRenameEdits(doc, pos, newName, token)).then(value => {

			if (!value) {
				return;
			}

			let result = <modes.IRenameResult>{
				currentName: undefined,
				edits: []
			};

			for (let entry of value.entries()) {
				let [uri, textEdits] = entry;
				for (let textEdit of textEdits) {
					result.edits.push({
						resource: <URI>uri,
						newText: textEdit.newText,
						range: TypeConverters.fromRange(textEdit.range)
					});
				}
			}
			return result;
		}, err => {
			if (typeof err === 'string') {
				return <modes.IRenameResult>{
					currentName: undefined,
					edits: undefined,
					rejectReason: err
				};
			}
			return TPromise.wrapError(err);
		});
	}
}

468 469 470 471
interface ISuggestion2 extends modes.ISuggestion {
	id: string;
}

472
class SuggestAdapter {
473

474
	private _documents: ExtHostModelService;
475
	private _provider: vscode.CompletionItemProvider;
476
	private _cache: { [key: string]: CompletionList } = Object.create(null);
477

478
	constructor(documents: ExtHostModelService, provider: vscode.CompletionItemProvider) {
479 480 481 482
		this._documents = documents;
		this._provider = provider;
	}

483
	provideCompletionItems(resource: URI, position: IPosition): TPromise<modes.ISuggestResult[]> {
484

485
		const doc = this._documents.getDocumentData(resource).document;
486 487 488 489 490 491
		const pos = TypeConverters.toPosition(position);
		const ran = doc.getWordRangeAtPosition(pos);

		const key = resource.toString();
		delete this._cache[key];

492
		return asWinJsPromise<vscode.CompletionItem[]|vscode.CompletionList>(token => this._provider.provideCompletionItems(doc, pos, token)).then(value => {
493

494
			let defaultSuggestions: modes.ISuggestResult = {
495
				suggestions: [],
496
				currentWord: ran ? doc.getText(new Range(ran.start.line, ran.start.character, pos.line, pos.character)) : '',
497
			};
498
			let allSuggestions: modes.ISuggestResult[] = [defaultSuggestions];
499

500 501 502 503 504 505
			let list: CompletionList;
			if (Array.isArray(value)) {
				list = new CompletionList(value);
			} else if (value instanceof CompletionList) {
				list = value;
				defaultSuggestions.incomplete = list.isIncomplete;
506 507 508
			} else if (!value) {
				// undefined and null are valid results
				return;
509
			} else {
510 511
				// warn about everything else
				console.warn('INVALID result from completion provider. expected CompletionItem-array or CompletionList but got:', value);
512 513
				return;
			}
514

515 516
			for (let i = 0; i < list.items.length; i++) {
				const item = list.items[i];
517
				const suggestion = <ISuggestion2> TypeConverters.Suggest.from(item);
518 519 520 521 522 523 524 525 526 527 528 529 530 531

				if (item.textEdit) {

					let editRange = item.textEdit.range;

					// invalid text edit
					if (!editRange.isSingleLine || editRange.start.line !== pos.line) {
						console.warn('INVALID text edit, must be single line and on the same line');
						continue;
					}

					// insert the text of the edit and create a dedicated
					// suggestion-container with overwrite[Before|After]
					suggestion.codeSnippet = item.textEdit.newText;
B
Benjamin Pasero 已提交
532 533
					suggestion.overwriteBefore = pos.character - editRange.start.character;
					suggestion.overwriteAfter = editRange.end.character - pos.character;
534 535

					allSuggestions.push({
536
						currentWord: doc.getText(editRange),
537 538
						suggestions: [suggestion],
						incomplete: list.isIncomplete
539 540 541 542 543 544 545 546 547 548 549
					});

				} else {
					defaultSuggestions.suggestions.push(suggestion);
				}

				// assign identifier to suggestion
				suggestion.id = String(i);
			}

			// cache for details call
550
			this._cache[key] = list;
551 552 553 554 555

			return allSuggestions;
		});
	}

556
	resolveCompletionItem(resource: URI, position: IPosition, suggestion: modes.ISuggestion): TPromise<modes.ISuggestion> {
557 558 559
		if (typeof this._provider.resolveCompletionItem !== 'function') {
			return TPromise.as(suggestion);
		}
560 561
		let list = this._cache[resource.toString()];
		if (!list) {
562 563
			return TPromise.as(suggestion);
		}
564
		let item = list.items[Number((<ISuggestion2> suggestion).id)];
565 566 567 568
		if (!item) {
			return TPromise.as(suggestion);
		}
		return asWinJsPromise(token => this._provider.resolveCompletionItem(item, token)).then(resolvedItem => {
569
			return TypeConverters.Suggest.from(resolvedItem || item);
570 571 572 573
		});
	}
}

A
Alex Dima 已提交
574
class SignatureHelpAdapter {
575

576
	private _documents: ExtHostModelService;
577 578
	private _provider: vscode.SignatureHelpProvider;

579
	constructor(documents: ExtHostModelService, provider: vscode.SignatureHelpProvider) {
580 581 582 583
		this._documents = documents;
		this._provider = provider;
	}

584
	provideSignatureHelp(resource: URI, position: IPosition): TPromise<modes.SignatureHelp> {
585

586
		const doc = this._documents.getDocumentData(resource).document;
587 588 589 590
		const pos = TypeConverters.toPosition(position);

		return asWinJsPromise(token => this._provider.provideSignatureHelp(doc, pos, token)).then(value => {
			if (value instanceof SignatureHelp) {
591
				return TypeConverters.SignatureHelp.from(value);
592 593 594 595 596
			}
		});
	}
}

A
Alex Dima 已提交
597
type Adapter = OutlineAdapter | CodeLensAdapter | DeclarationAdapter | HoverProviderAdapter
598 599
	| OccurrencesAdapter | ReferenceAdapter | QuickFixAdapter | DocumentFormattingAdapter
	| RangeFormattingAdapter | OnTypeFormattingAdapter | NavigateTypeAdapter | RenameAdapter
A
Alex Dima 已提交
600
	| SuggestAdapter | SignatureHelpAdapter;
J
Johannes Rieken 已提交
601

A
Alex Dima 已提交
602
@Remotable.ExtHostContext('ExtHostLanguageFeatures')
J
Johannes Rieken 已提交
603 604
export class ExtHostLanguageFeatures {

605
	private static _handlePool: number = 0;
J
Johannes Rieken 已提交
606 607

	private _proxy: MainThreadLanguageFeatures;
608 609
	private _documents: ExtHostModelService;
	private _commands: ExtHostCommands;
610
	private _diagnostics: ExtHostDiagnostics;
J
Johannes Rieken 已提交
611 612 613 614
	private _adapter: { [handle: number]: Adapter } = Object.create(null);

	constructor( @IThreadService threadService: IThreadService) {
		this._proxy = threadService.getRemotable(MainThreadLanguageFeatures);
615 616
		this._documents = threadService.getRemotable(ExtHostModelService);
		this._commands = threadService.getRemotable(ExtHostCommands);
617
		this._diagnostics = threadService.getRemotable(ExtHostDiagnostics);
J
Johannes Rieken 已提交
618 619 620 621 622 623 624 625 626
	}

	private _createDisposable(handle: number): Disposable {
		return new Disposable(() => {
			delete this._adapter[handle];
			this._proxy.$unregister(handle);
		});
	}

627 628 629 630
	private _nextHandle(): number {
		return ExtHostLanguageFeatures._handlePool++;
	}

J
Johannes Rieken 已提交
631 632 633 634 635 636
	private _withAdapter<A, R>(handle: number, ctor: { new (...args: any[]): A }, callback: (adapter: A) => TPromise<R>): TPromise<R> {
		let adapter = this._adapter[handle];
		if (!(adapter instanceof ctor)) {
			return TPromise.wrapError(new Error('no adapter found'));
		}
		return callback(<any> adapter);
637 638
	}

J
Johannes Rieken 已提交
639 640 641
	// --- outline

	registerDocumentSymbolProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentSymbolProvider): vscode.Disposable {
642 643
		const handle = this._nextHandle();
		this._adapter[handle] = new OutlineAdapter(this._documents, provider);
644
		this._proxy.$registerOutlineSupport(handle, selector);
J
Johannes Rieken 已提交
645 646 647
		return this._createDisposable(handle);
	}

648
	$getOutline(handle: number, resource: URI): TPromise<modes.IOutlineEntry[]> {
J
Johannes Rieken 已提交
649
		return this._withAdapter(handle, OutlineAdapter, adapter => adapter.getOutline(resource));
J
Johannes Rieken 已提交
650
	}
651 652 653 654 655

	// --- code lens

	registerCodeLensProvider(selector: vscode.DocumentSelector, provider: vscode.CodeLensProvider): vscode.Disposable {
		const handle = this._nextHandle();
656
		this._adapter[handle] = new CodeLensAdapter(this._documents, this._commands, provider);
657 658 659 660
		this._proxy.$registerCodeLensSupport(handle, selector);
		return this._createDisposable(handle);
	}

J
Johannes Rieken 已提交
661 662
	$findCodeLensSymbols(handle: number, resource: URI): TPromise<modes.ICodeLensSymbol[]> {
		return this._withAdapter(handle, CodeLensAdapter, adapter => adapter.findCodeLensSymbols(resource));
663 664
	}

665
	$resolveCodeLensSymbol(handle: number, resource: URI, symbol: modes.ICodeLensSymbol): TPromise<modes.ICodeLensSymbol> {
J
Johannes Rieken 已提交
666 667 668 669 670 671 672 673 674 675
		return this._withAdapter(handle, CodeLensAdapter, adapter => adapter.resolveCodeLensSymbol(resource, symbol));
	}

	// --- declaration

	registerDefinitionProvider(selector: vscode.DocumentSelector, provider: vscode.DefinitionProvider): vscode.Disposable {
		const handle = this._nextHandle();
		this._adapter[handle] = new DeclarationAdapter(this._documents, provider);
		this._proxy.$registerDeclaractionSupport(handle, selector);
		return this._createDisposable(handle);
676 677
	}

J
Johannes Rieken 已提交
678 679 680
	$findDeclaration(handle: number, resource: URI, position: IPosition): TPromise<modes.IReference[]> {
		return this._withAdapter(handle, DeclarationAdapter, adapter => adapter.findDeclaration(resource, position));
	}
J
Johannes Rieken 已提交
681 682 683 684 685

	// --- extra info

	registerHoverProvider(selector: vscode.DocumentSelector, provider: vscode.HoverProvider): vscode.Disposable {
		const handle = this._nextHandle();
A
Alex Dima 已提交
686 687
		this._adapter[handle] = new HoverProviderAdapter(this._documents, provider);
		this._proxy.$registerHoverProvider(handle, selector);
J
Johannes Rieken 已提交
688 689 690
		return this._createDisposable(handle);
	}

691
	$provideHover(handle: number, resource: URI, position: IPosition): TPromise<modes.Hover> {
A
Alex Dima 已提交
692
		return this._withAdapter(handle, HoverProviderAdapter, adpater => adpater.provideHover(resource, position));
J
Johannes Rieken 已提交
693
	}
694

J
Johannes Rieken 已提交
695
	// --- occurrences
696 697 698 699 700 701 702 703

	registerDocumentHighlightProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentHighlightProvider): vscode.Disposable {
		const handle = this._nextHandle();
		this._adapter[handle] = new OccurrencesAdapter(this._documents, provider);
		this._proxy.$registerOccurrencesSupport(handle, selector);
		return this._createDisposable(handle);
	}

704
	$findOccurrences(handle: number, resource: URI, position: IPosition): TPromise<modes.IOccurence[]> {
705 706
		return this._withAdapter(handle, OccurrencesAdapter, adapter => adapter.findOccurrences(resource, position));
	}
J
Johannes Rieken 已提交
707 708 709 710 711 712 713 714 715 716 717 718 719 720

	// --- references

	registerReferenceProvider(selector: vscode.DocumentSelector, provider: vscode.ReferenceProvider): vscode.Disposable {
		const handle = this._nextHandle();
		this._adapter[handle] = new ReferenceAdapter(this._documents, provider);
		this._proxy.$registerReferenceSupport(handle, selector);
		return this._createDisposable(handle);
	}

	$findReferences(handle: number, resource: URI, position: IPosition, includeDeclaration: boolean): TPromise<modes.IReference[]> {
		return this._withAdapter(handle, ReferenceAdapter, adapter => adapter.findReferences(resource, position, includeDeclaration));
	}

J
Johannes Rieken 已提交
721 722 723 724
	// --- quick fix

	registerCodeActionProvider(selector: vscode.DocumentSelector, provider: vscode.CodeActionProvider): vscode.Disposable {
		const handle = this._nextHandle();
725
		this._adapter[handle] = new QuickFixAdapter(this._documents, this._commands, this._diagnostics, provider);
J
Johannes Rieken 已提交
726 727 728 729
		this._proxy.$registerQuickFixSupport(handle, selector);
		return this._createDisposable(handle);
	}

730 731
	$getQuickFixes(handle: number, resource: URI, range: IRange): TPromise<modes.IQuickFix[]> {
		return this._withAdapter(handle, QuickFixAdapter, adapter => adapter.getQuickFixes(resource, range));
J
Johannes Rieken 已提交
732 733
	}

734 735
	$runQuickFixAction(handle: number, resource: URI, range: IRange, quickFix: modes.IQuickFix): any {
		return this._withAdapter(handle, QuickFixAdapter, adapter => adapter.runQuickFixAction(resource, range, quickFix));
J
Johannes Rieken 已提交
736
	}
737 738 739 740 741 742 743 744 745 746

	// --- formatting

	registerDocumentFormattingEditProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentFormattingEditProvider): vscode.Disposable {
		const handle = this._nextHandle();
		this._adapter[handle] = new DocumentFormattingAdapter(this._documents, provider);
		this._proxy.$registerDocumentFormattingSupport(handle, selector);
		return this._createDisposable(handle);
	}

747
	$formatDocument(handle: number, resource: URI, options: modes.IFormattingOptions): TPromise<ISingleEditOperation[]> {
748 749 750 751 752 753 754 755 756 757
		return this._withAdapter(handle, DocumentFormattingAdapter, adapter => adapter.formatDocument(resource, options));
	}

	registerDocumentRangeFormattingEditProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentRangeFormattingEditProvider): vscode.Disposable {
		const handle = this._nextHandle();
		this._adapter[handle] = new RangeFormattingAdapter(this._documents, provider);
		this._proxy.$registerRangeFormattingSupport(handle, selector);
		return this._createDisposable(handle);
	}

758
	$formatRange(handle: number, resource: URI, range: IRange, options: modes.IFormattingOptions): TPromise<ISingleEditOperation[]> {
759 760 761 762 763 764 765 766 767 768
		return this._withAdapter(handle, RangeFormattingAdapter, adapter => adapter.formatRange(resource, range, options));
	}

	registerOnTypeFormattingEditProvider(selector: vscode.DocumentSelector, provider: vscode.OnTypeFormattingEditProvider, triggerCharacters: string[]): vscode.Disposable {
		const handle = this._nextHandle();
		this._adapter[handle] = new OnTypeFormattingAdapter(this._documents, provider);
		this._proxy.$registerOnTypeFormattingSupport(handle, selector, triggerCharacters);
		return this._createDisposable(handle);
	}

769
	$formatAfterKeystroke(handle: number, resource: URI, position: IPosition, ch: string, options: modes.IFormattingOptions): TPromise<ISingleEditOperation[]> {
770 771 772
		return this._withAdapter(handle, OnTypeFormattingAdapter, adapter => adapter.formatAfterKeystroke(resource, position, ch, options));
	}

773 774 775 776 777 778 779 780 781 782 783 784
	// --- navigate types

	registerWorkspaceSymbolProvider(provider: vscode.WorkspaceSymbolProvider): vscode.Disposable {
		const handle = this._nextHandle();
		this._adapter[handle] = new NavigateTypeAdapter(provider);
		this._proxy.$registerNavigateTypeSupport(handle);
		return this._createDisposable(handle);
	}

	$getNavigateToItems(handle: number, search: string): TPromise<ITypeBearing[]> {
		return this._withAdapter(handle, NavigateTypeAdapter, adapter => adapter.getNavigateToItems(search));
	}
J
Johannes Rieken 已提交
785 786 787 788 789 790 791 792 793 794 795 796 797

	// --- rename

	registerRenameProvider(selector: vscode.DocumentSelector, provider: vscode.RenameProvider): vscode.Disposable {
		const handle = this._nextHandle();
		this._adapter[handle] = new RenameAdapter(this._documents, provider);
		this._proxy.$registerRenameSupport(handle, selector);
		return this._createDisposable(handle);
	}

	$rename(handle: number, resource: URI, position: IPosition, newName: string): TPromise<modes.IRenameResult> {
		return this._withAdapter(handle, RenameAdapter, adapter => adapter.rename(resource, position, newName));
	}
798 799 800 801 802 803 804 805 806 807

	// --- suggestion

	registerCompletionItemProvider(selector: vscode.DocumentSelector, provider: vscode.CompletionItemProvider, triggerCharacters: string[]): vscode.Disposable {
		const handle = this._nextHandle();
		this._adapter[handle] = new SuggestAdapter(this._documents, provider);
		this._proxy.$registerSuggestSupport(handle, selector, triggerCharacters);
		return this._createDisposable(handle);
	}

808 809
	$provideCompletionItems(handle: number, resource: URI, position: IPosition): TPromise<modes.ISuggestResult[]> {
		return this._withAdapter(handle, SuggestAdapter, adapter => adapter.provideCompletionItems(resource, position));
810 811
	}

812 813
	$resolveCompletionItem(handle: number, resource: URI, position: IPosition, suggestion: modes.ISuggestion): TPromise<modes.ISuggestion> {
		return this._withAdapter(handle, SuggestAdapter, adapter => adapter.resolveCompletionItem(resource, position, suggestion));
814
	}
815 816 817 818 819

	// --- parameter hints

	registerSignatureHelpProvider(selector: vscode.DocumentSelector, provider: vscode.SignatureHelpProvider, triggerCharacters: string[]): vscode.Disposable {
		const handle = this._nextHandle();
A
Alex Dima 已提交
820 821
		this._adapter[handle] = new SignatureHelpAdapter(this._documents, provider);
		this._proxy.$registerSignatureHelpProvider(handle, selector, triggerCharacters);
822 823 824
		return this._createDisposable(handle);
	}

825
	$provideSignatureHelp(handle: number, resource: URI, position: IPosition): TPromise<modes.SignatureHelp> {
A
Alex Dima 已提交
826
		return this._withAdapter(handle, SignatureHelpAdapter, adapter => adapter.provideSignatureHelp(resource, position));
827
	}
J
Johannes Rieken 已提交
828 829 830 831 832 833
}

@Remotable.MainContext('MainThreadLanguageFeatures')
export class MainThreadLanguageFeatures {

	private _proxy: ExtHostLanguageFeatures;
834
	private _registrations: { [handle: number]: IDisposable; } = Object.create(null);
J
Johannes Rieken 已提交
835

836
	constructor( @IThreadService threadService: IThreadService) {
J
Johannes Rieken 已提交
837 838 839 840
		this._proxy = threadService.getRemotable(ExtHostLanguageFeatures);
	}

	$unregister(handle: number): TPromise<any> {
841 842 843 844
		let registration = this._registrations[handle];
		if (registration) {
			registration.dispose();
			delete this._registrations[handle];
J
Johannes Rieken 已提交
845 846 847 848 849 850 851
		}
		return undefined;
	}

	// --- outline

	$registerOutlineSupport(handle: number, selector: vscode.DocumentSelector): TPromise<any> {
852 853
		this._registrations[handle] = modes.OutlineRegistry.register(selector, <modes.IOutlineSupport>{
			getOutline: (resource: URI): TPromise<modes.IOutlineEntry[]> => {
J
Johannes Rieken 已提交
854 855 856
				return this._proxy.$getOutline(handle, resource);
			}
		});
857 858 859 860 861 862
		return undefined;
	}

	// --- code lens

	$registerCodeLensSupport(handle: number, selector: vscode.DocumentSelector): TPromise<any> {
863
		this._registrations[handle] = modes.CodeLensRegistry.register(selector, <modes.ICodeLensSupport>{
864 865 866
			findCodeLensSymbols: (resource: URI): TPromise<modes.ICodeLensSymbol[]> => {
				return this._proxy.$findCodeLensSymbols(handle, resource);
			},
J
Johannes Rieken 已提交
867
			resolveCodeLensSymbol: (resource: URI, symbol: modes.ICodeLensSymbol): TPromise<modes.ICodeLensSymbol> => {
868 869 870
				return this._proxy.$resolveCodeLensSymbol(handle, resource, symbol);
			}
		});
J
Johannes Rieken 已提交
871 872
		return undefined;
	}
J
Johannes Rieken 已提交
873 874 875 876

	// --- declaration

	$registerDeclaractionSupport(handle: number, selector: vscode.DocumentSelector): TPromise<any> {
877
		this._registrations[handle] = modes.DeclarationRegistry.register(selector, <modes.IDeclarationSupport>{
J
Johannes Rieken 已提交
878 879 880 881 882 883
			findDeclaration: (resource: URI, position: IPosition): TPromise<modes.IReference[]> => {
				return this._proxy.$findDeclaration(handle, resource, position);
			}
		});
		return undefined;
	}
J
Johannes Rieken 已提交
884 885 886

	// --- extra info

A
Alex Dima 已提交
887 888
	$registerHoverProvider(handle: number, selector: vscode.DocumentSelector): TPromise<any> {
		this._registrations[handle] = modes.HoverProviderRegistry.register(selector, <modes.HoverProvider>{
889 890
			provideHover: (model:IReadOnlyModel, position:IEditorPosition, token:CancellationToken): Thenable<modes.Hover> => {
				return wireCancellationToken(token, this._proxy.$provideHover(handle, model.getAssociatedResource(), position));
J
Johannes Rieken 已提交
891 892 893 894
			}
		});
		return undefined;
	}
895 896 897 898

	// --- occurrences

	$registerOccurrencesSupport(handle: number, selector: vscode.DocumentSelector): TPromise<any> {
899
		this._registrations[handle] = modes.OccurrencesRegistry.register(selector, <modes.IOccurrencesSupport>{
900 901 902 903 904 905
			findOccurrences: (resource: URI, position: IPosition): TPromise<modes.IOccurence[]> => {
				return this._proxy.$findOccurrences(handle, resource, position);
			}
		});
		return undefined;
	}
J
Johannes Rieken 已提交
906 907 908 909

	// --- references

	$registerReferenceSupport(handle: number, selector: vscode.DocumentSelector): TPromise<any> {
910
		this._registrations[handle] = modes.ReferenceSearchRegistry.register(selector, <modes.IReferenceSupport>{
J
Johannes Rieken 已提交
911 912 913 914 915 916
			findReferences: (resource: URI, position: IPosition, includeDeclaration: boolean): TPromise<modes.IReference[]> => {
				return this._proxy.$findReferences(handle, resource, position, includeDeclaration);
			}
		});
		return undefined;
	}
J
Johannes Rieken 已提交
917 918 919 920

	// --- quick fix

	$registerQuickFixSupport(handle: number, selector: vscode.DocumentSelector): TPromise<any> {
921
		this._registrations[handle] = modes.QuickFixRegistry.register(selector, <modes.IQuickFixSupport>{
J
Johannes Rieken 已提交
922
			getQuickFixes: (resource: URI, range: IRange): TPromise<modes.IQuickFix[]> => {
923
				return this._proxy.$getQuickFixes(handle, resource, range);
J
Johannes Rieken 已提交
924
			},
925 926
			runQuickFixAction: (resource: URI, range: IRange, quickFix: modes.IQuickFix) => {
				return this._proxy.$runQuickFixAction(handle, resource, range, quickFix);
J
Johannes Rieken 已提交
927 928 929 930
			}
		});
		return undefined;
	}
931 932 933 934

	// --- formatting

	$registerDocumentFormattingSupport(handle: number, selector: vscode.DocumentSelector): TPromise<any> {
935
		this._registrations[handle] = modes.FormatRegistry.register(selector, <modes.IFormattingSupport>{
936 937 938 939 940 941 942 943
			formatDocument: (resource: URI, options: modes.IFormattingOptions): TPromise <ISingleEditOperation[] > => {
				return this._proxy.$formatDocument(handle, resource, options);
			}
		});
		return undefined;
	}

	$registerRangeFormattingSupport(handle: number, selector: vscode.DocumentSelector): TPromise<any> {
944
		this._registrations[handle] = modes.FormatRegistry.register(selector, <modes.IFormattingSupport>{
945 946 947 948 949 950 951 952
			formatRange: (resource: URI, range: IRange, options: modes.IFormattingOptions): TPromise <ISingleEditOperation[] > => {
				return this._proxy.$formatRange(handle, resource, range, options);
			}
		});
		return undefined;
	}

	$registerOnTypeFormattingSupport(handle: number, selector: vscode.DocumentSelector, autoFormatTriggerCharacters: string[]): TPromise<any> {
953
		this._registrations[handle] = modes.FormatOnTypeRegistry.register(selector, <modes.IFormattingSupport>{
954 955 956 957 958 959 960 961 962

			autoFormatTriggerCharacters,

			formatAfterKeystroke: (resource: URI, position: IPosition, ch: string, options: modes.IFormattingOptions): TPromise<ISingleEditOperation[]> => {
				return this._proxy.$formatAfterKeystroke(handle, resource, position, ch, options);
			}
		});
		return undefined;
	}
963 964 965 966 967 968 969 970 971 972 973

	// --- navigate type

	$registerNavigateTypeSupport(handle: number): TPromise<any> {
		this._registrations[handle] = NavigateTypesSupportRegistry.register(<INavigateTypesSupport>{
			getNavigateToItems: (search: string): TPromise<ITypeBearing[]> => {
				return this._proxy.$getNavigateToItems(handle, search);
			}
		});
		return undefined;
	}
J
Johannes Rieken 已提交
974 975 976 977

	// --- rename

	$registerRenameSupport(handle: number, selector: vscode.DocumentSelector): TPromise<any> {
978
		this._registrations[handle] = modes.RenameRegistry.register(selector, <modes.IRenameSupport>{
J
Johannes Rieken 已提交
979 980 981 982 983 984
			rename: (resource: URI, position: IPosition, newName: string): TPromise<modes.IRenameResult> => {
				return this._proxy.$rename(handle, resource, position, newName);
			}
		});
		return undefined;
	}
985 986 987 988

	// --- suggest

	$registerSuggestSupport(handle: number, selector: vscode.DocumentSelector, triggerCharacters: string[]): TPromise<any> {
989
		this._registrations[handle] = modes.SuggestRegistry.register(selector, <modes.ISuggestSupport>{
990
			triggerCharacters: triggerCharacters,
991
			shouldAutotriggerSuggest: true,
992 993
			provideCompletionItems: (model:IReadOnlyModel, position:IEditorPosition, token:CancellationToken): Thenable<modes.ISuggestResult[]> => {
				return wireCancellationToken(token, this._proxy.$provideCompletionItems(handle, model.getAssociatedResource(), position));
994
			},
995 996
			resolveCompletionItem: (model:IReadOnlyModel, position:IEditorPosition, suggestion: modes.ISuggestion, token: CancellationToken): Thenable<modes.ISuggestion> => {
				return wireCancellationToken(token, this._proxy.$resolveCompletionItem(handle, model.getAssociatedResource(), position, suggestion));
997 998 999 1000
			}
		});
		return undefined;
	}
1001 1002 1003

	// --- parameter hints

A
Alex Dima 已提交
1004 1005
	$registerSignatureHelpProvider(handle: number, selector: vscode.DocumentSelector, triggerCharacter: string[]): TPromise<any> {
		this._registrations[handle] = modes.SignatureHelpProviderRegistry.register(selector, <modes.SignatureHelpProvider>{
1006

A
Alex Dima 已提交
1007
			signatureHelpTriggerCharacters: triggerCharacter,
1008

1009 1010
			provideSignatureHelp: (model:IReadOnlyModel, position:IEditorPosition, token:CancellationToken): Thenable<modes.SignatureHelp> => {
				return wireCancellationToken(token, this._proxy.$provideSignatureHelp(handle, model.getAssociatedResource(), position));
1011
			}
1012

1013 1014 1015
		});
		return undefined;
	}
1016
}