Skip to content

Commit 3535261

Browse files
committed
use suggest lifecycle instead of automagic heap tracking, microsoft#18682
1 parent d81b305 commit 3535261

3 files changed

Lines changed: 60 additions & 27 deletions

File tree

src/vs/workbench/api/electron-browser/mainThreadLanguageFeatures.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,16 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
236236
this._registrations[handle] = modes.SuggestRegistry.register(selector, <modes.ISuggestSupport>{
237237
triggerCharacters,
238238
provideCompletionItems: (model: IReadOnlyModel, position: EditorPosition, token: CancellationToken): Thenable<modes.ISuggestResult> => {
239-
return this._heapService.trackRecursive(wireCancellationToken(token, this._proxy.$provideCompletionItems(handle, model.uri, position)));
239+
return wireCancellationToken(token, this._proxy.$provideCompletionItems(handle, model.uri, position)).then(result => {
240+
if (!result) {
241+
return result;
242+
}
243+
return {
244+
suggestions: result.suggestions,
245+
incomplete: result.incomplete,
246+
dispose: () => this._proxy.$releaseCompletionItems(handle, result._id)
247+
};
248+
});
240249
},
241250
resolveCompletionItem: (model: IReadOnlyModel, position: EditorPosition, suggestion: modes.ISuggestion, token: CancellationToken): Thenable<modes.ISuggestion> => {
242251
return wireCancellationToken(token, this._proxy.$resolveCompletionItem(handle, model.uri, position, suggestion));

src/vs/workbench/api/node/extHost.protocol.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -501,6 +501,18 @@ export interface IRawColorInfo {
501501

502502
export type IRawColorFormatMap = [number, string][];
503503

504+
505+
export interface IExtHostSuggestion extends modes.ISuggestion {
506+
_id: number;
507+
_parentId: number;
508+
}
509+
510+
export interface IExtHostSuggestResult {
511+
_id: number;
512+
suggestions: IExtHostSuggestion[];
513+
incomplete?: boolean;
514+
}
515+
504516
export interface ExtHostLanguageFeaturesShape {
505517
$provideDocumentSymbols(handle: number, resource: URI): TPromise<modes.SymbolInformation[]>;
506518
$provideCodeLenses(handle: number, resource: URI): TPromise<modes.ICodeLensSymbol[]>;
@@ -518,8 +530,9 @@ export interface ExtHostLanguageFeaturesShape {
518530
$provideWorkspaceSymbols(handle: number, search: string): TPromise<modes.SymbolInformation[]>;
519531
$resolveWorkspaceSymbol(handle: number, symbol: modes.SymbolInformation): TPromise<modes.SymbolInformation>;
520532
$provideRenameEdits(handle: number, resource: URI, position: IPosition, newName: string): TPromise<modes.WorkspaceEdit>;
521-
$provideCompletionItems(handle: number, resource: URI, position: IPosition): TPromise<modes.ISuggestResult>;
533+
$provideCompletionItems(handle: number, resource: URI, position: IPosition): TPromise<IExtHostSuggestResult>;
522534
$resolveCompletionItem(handle: number, resource: URI, position: IPosition, suggestion: modes.ISuggestion): TPromise<modes.ISuggestion>;
535+
$releaseCompletionItems(handle: number, id: number): void;
523536
$provideSignatureHelp(handle: number, resource: URI, position: IPosition): TPromise<modes.SignatureHelp>;
524537
$provideDocumentLinks(handle: number, resource: URI): TPromise<modes.ILink[]>;
525538
$provideDocumentColors(handle: number, resource: URI): TPromise<IRawColorInfo[]>;

src/vs/workbench/api/node/extHostLanguageFeatures.ts

Lines changed: 36 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import { TPromise } from 'vs/base/common/winjs.base';
99
import { mixin } from 'vs/base/common/objects';
1010
import * as vscode from 'vscode';
1111
import * as TypeConverters from 'vs/workbench/api/node/extHostTypeConverters';
12-
import { Range, Disposable, CompletionList, CompletionItem, SnippetString } from 'vs/workbench/api/node/extHostTypes';
12+
import { Range, Disposable, CompletionList, SnippetString } from 'vs/workbench/api/node/extHostTypes';
1313
import { ISingleEditOperation } from 'vs/editor/common/editorCommon';
1414
import * as modes from 'vs/editor/common/modes';
1515
import { ExtHostHeapService } from 'vs/workbench/api/node/extHostHeapService';
@@ -18,7 +18,7 @@ import { ExtHostCommands, CommandsConverter } from 'vs/workbench/api/node/extHos
1818
import { ExtHostDiagnostics } from 'vs/workbench/api/node/extHostDiagnostics';
1919
import { IWorkspaceSymbolProvider } from 'vs/workbench/parts/search/common/search';
2020
import { asWinJsPromise } from 'vs/base/common/async';
21-
import { MainContext, MainThreadTelemetryShape, MainThreadLanguageFeaturesShape, ExtHostLanguageFeaturesShape, ObjectIdentifier, IRawColorInfo, IRawColorFormatMap, IMainContext } from './extHost.protocol';
21+
import { MainContext, MainThreadTelemetryShape, MainThreadLanguageFeaturesShape, ExtHostLanguageFeaturesShape, ObjectIdentifier, IRawColorInfo, IRawColorFormatMap, IMainContext, IExtHostSuggestResult, IExtHostSuggestion } from './extHost.protocol';
2222
import { regExpLeadsToEndlessLoop } from 'vs/base/common/strings';
2323
import { IPosition } from 'vs/editor/common/core/position';
2424
import { IRange } from 'vs/editor/common/core/range';
@@ -471,24 +471,28 @@ class SuggestAdapter {
471471

472472
private _documents: ExtHostDocuments;
473473
private _commands: CommandsConverter;
474-
private _heapService: ExtHostHeapService;
475474
private _provider: vscode.CompletionItemProvider;
476475

477-
constructor(documents: ExtHostDocuments, commands: CommandsConverter, heapService: ExtHostHeapService, provider: vscode.CompletionItemProvider) {
476+
private _cache = new Map<number, vscode.CompletionItem[]>();
477+
private _idPool = 0;
478+
479+
constructor(documents: ExtHostDocuments, commands: CommandsConverter, provider: vscode.CompletionItemProvider) {
478480
this._documents = documents;
479481
this._commands = commands;
480-
this._heapService = heapService;
481482
this._provider = provider;
482483
}
483484

484-
provideCompletionItems(resource: URI, position: IPosition): TPromise<modes.ISuggestResult> {
485+
provideCompletionItems(resource: URI, position: IPosition): TPromise<IExtHostSuggestResult> {
485486

486487
const doc = this._documents.getDocumentData(resource).document;
487488
const pos = TypeConverters.toPosition(position);
488489

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

491-
const result: modes.ISuggestResult = {
492+
const _id = this._idPool++;
493+
494+
const result: IExtHostSuggestResult = {
495+
_id,
492496
suggestions: [],
493497
};
494498

@@ -509,19 +513,15 @@ class SuggestAdapter {
509513
const wordRangeBeforePos = (doc.getWordRangeAtPosition(pos) || new Range(pos, pos))
510514
.with({ end: pos });
511515

512-
for (const item of list.items) {
513-
514-
const suggestion = this._convertCompletionItem(item, pos, wordRangeBeforePos);
515-
516-
// bad completion item
517-
if (!suggestion) {
518-
// converter did warn
519-
continue;
516+
for (let i = 0; i < list.items.length; i++) {
517+
const suggestion = this._convertCompletionItem(list.items[i], pos, wordRangeBeforePos, i, _id);
518+
// check for bad completion item
519+
// for the converter did warn
520+
if (suggestion) {
521+
result.suggestions.push(suggestion);
520522
}
521-
522-
ObjectIdentifier.mixin(suggestion, this._heapService.keep(item));
523-
result.suggestions.push(suggestion);
524523
}
524+
this._cache.set(_id, list.items);
525525

526526
return result;
527527
});
@@ -533,8 +533,8 @@ class SuggestAdapter {
533533
return TPromise.as(suggestion);
534534
}
535535

536-
const id = ObjectIdentifier.of(suggestion);
537-
const item = this._heapService.get<CompletionItem>(id);
536+
const { _parentId, _id } = (<IExtHostSuggestion>suggestion);
537+
const item = this._cache.has(_parentId) && this._cache.get(_parentId)[_id];
538538
if (!item) {
539539
return TPromise.as(suggestion);
540540
}
@@ -548,7 +548,7 @@ class SuggestAdapter {
548548
const doc = this._documents.getDocumentData(resource).document;
549549
const pos = TypeConverters.toPosition(position);
550550
const wordRangeBeforePos = (doc.getWordRangeAtPosition(pos) || new Range(pos, pos)).with({ end: pos });
551-
const newSuggestion = this._convertCompletionItem(resolvedItem, pos, wordRangeBeforePos);
551+
const newSuggestion = this._convertCompletionItem(resolvedItem, pos, wordRangeBeforePos, _id, _parentId);
552552
if (newSuggestion) {
553553
mixin(suggestion, newSuggestion, true);
554554
}
@@ -557,13 +557,20 @@ class SuggestAdapter {
557557
});
558558
}
559559

560-
private _convertCompletionItem(item: vscode.CompletionItem, position: vscode.Position, defaultRange: vscode.Range): modes.ISuggestion {
560+
releaseCompletionItems(id: number): any {
561+
this._cache.delete(id);
562+
}
563+
564+
private _convertCompletionItem(item: vscode.CompletionItem, position: vscode.Position, defaultRange: vscode.Range, _id: number, _parentId: number): IExtHostSuggestion {
561565
if (typeof item.label !== 'string' || item.label.length === 0) {
562566
console.warn('INVALID text edit -> must have at least a label');
563567
return undefined;
564568
}
565569

566-
const result: modes.ISuggestion = {
570+
const result: IExtHostSuggestion = {
571+
//
572+
_id,
573+
_parentId,
567574
//
568575
label: item.label,
569576
type: TypeConverters.CompletionItemKind.from(item.kind),
@@ -994,19 +1001,23 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
9941001

9951002
registerCompletionItemProvider(selector: vscode.DocumentSelector, provider: vscode.CompletionItemProvider, triggerCharacters: string[]): vscode.Disposable {
9961003
const handle = this._nextHandle();
997-
this._adapter.set(handle, new SuggestAdapter(this._documents, this._commands.converter, this._heapService, provider));
1004+
this._adapter.set(handle, new SuggestAdapter(this._documents, this._commands.converter, provider));
9981005
this._proxy.$registerSuggestSupport(handle, selector, triggerCharacters);
9991006
return this._createDisposable(handle);
10001007
}
10011008

1002-
$provideCompletionItems(handle: number, resource: URI, position: IPosition): TPromise<modes.ISuggestResult> {
1009+
$provideCompletionItems(handle: number, resource: URI, position: IPosition): TPromise<IExtHostSuggestResult> {
10031010
return this._withAdapter(handle, SuggestAdapter, adapter => adapter.provideCompletionItems(resource, position));
10041011
}
10051012

10061013
$resolveCompletionItem(handle: number, resource: URI, position: IPosition, suggestion: modes.ISuggestion): TPromise<modes.ISuggestion> {
10071014
return this._withAdapter(handle, SuggestAdapter, adapter => adapter.resolveCompletionItem(resource, position, suggestion));
10081015
}
10091016

1017+
$releaseCompletionItems(handle: number, id: number): void {
1018+
this._withAdapter(handle, SuggestAdapter, adapter => adapter.releaseCompletionItems(id));
1019+
}
1020+
10101021
// --- parameter hints
10111022

10121023
registerSignatureHelpProvider(selector: vscode.DocumentSelector, provider: vscode.SignatureHelpProvider, triggerCharacters: string[]): vscode.Disposable {

0 commit comments

Comments
 (0)