diff --git a/src/vs/workbench/api/browser/mainThreadLanguageFeatures.ts b/src/vs/workbench/api/browser/mainThreadLanguageFeatures.ts index 4937473a077..c7cd1af77e0 100644 --- a/src/vs/workbench/api/browser/mainThreadLanguageFeatures.ts +++ b/src/vs/workbench/api/browser/mainThreadLanguageFeatures.ts @@ -377,7 +377,6 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha command: data.m, // not-standard _id: data.x, - _pid: data.y }; } @@ -392,14 +391,14 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha return { suggestions: result.b.map(d => MainThreadLanguageFeatures._inflateSuggestDto(result.a, d)), incomplete: result.c, - dispose: () => this._proxy.$releaseCompletionItems(handle, result.x) + dispose: () => typeof result.x === 'number' && this._proxy.$releaseCompletionItems(handle, result.x) }; }); } }; if (supportsResolveDetails) { provider.resolveCompletionItem = (model, position, suggestion, token) => { - return this._proxy.$resolveCompletionItem(handle, model.uri, position, suggestion._id, suggestion._pid, token).then(result => { + return this._proxy.$resolveCompletionItem(handle, model.uri, position, suggestion._id, token).then(result => { if (!result) { return suggestion; } @@ -447,7 +446,11 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha }; if (supportsResolve) { provider.resolveLink = (link, token) => { - return this._proxy.$resolveDocumentLink(handle, link as LinkDto, token).then(obj => { + const dto: LinkDto = link; + if (!dto.cacheId) { + return link; + } + return this._proxy.$resolveDocumentLink(handle, dto.cacheId, token).then(obj => { return obj && MainThreadLanguageFeatures._reviveLinkDTO(obj); }); }; diff --git a/src/vs/workbench/api/common/extHost.protocol.ts b/src/vs/workbench/api/common/extHost.protocol.ts index 7fda02d342c..56aa498c609 100644 --- a/src/vs/workbench/api/common/extHost.protocol.ts +++ b/src/vs/workbench/api/common/extHost.protocol.ts @@ -870,12 +870,11 @@ export interface SuggestDataDto { l/* additionalTextEdits */?: ISingleEditOperation[]; m/* command */?: modes.Command; // not-standard - x: number; - y: number; + x?: ChainedCacheId; } export interface SuggestResultDto { - x: number; + x?: number; a: IRange; b: SuggestDataDto[]; c?: boolean; @@ -1008,11 +1007,11 @@ export interface ExtHostLanguageFeaturesShape { $provideRenameEdits(handle: number, resource: UriComponents, position: IPosition, newName: string, token: CancellationToken): Promise; $resolveRenameLocation(handle: number, resource: UriComponents, position: IPosition, token: CancellationToken): Promise; $provideCompletionItems(handle: number, resource: UriComponents, position: IPosition, context: modes.CompletionContext, token: CancellationToken): Promise; - $resolveCompletionItem(handle: number, resource: UriComponents, position: IPosition, id: number, pid: number, token: CancellationToken): Promise; + $resolveCompletionItem(handle: number, resource: UriComponents, position: IPosition, id: ChainedCacheId, token: CancellationToken): Promise; $releaseCompletionItems(handle: number, id: number): void; $provideSignatureHelp(handle: number, resource: UriComponents, position: IPosition, context: modes.SignatureHelpContext, token: CancellationToken): Promise; $provideDocumentLinks(handle: number, resource: UriComponents, token: CancellationToken): Promise; - $resolveDocumentLink(handle: number, link: LinkDto, token: CancellationToken): Promise; + $resolveDocumentLink(handle: number, id: ChainedCacheId, token: CancellationToken): Promise; $releaseDocumentLinks(handle: number, id: number): void; $provideDocumentColors(handle: number, resource: UriComponents, token: CancellationToken): Promise; $provideColorPresentations(handle: number, resource: UriComponents, colorInfo: IRawColorInfo, token: CancellationToken): Promise; diff --git a/src/vs/workbench/api/node/extHostLanguageFeatures.ts b/src/vs/workbench/api/node/extHostLanguageFeatures.ts index b9b7b890342..0a3a2370bfc 100644 --- a/src/vs/workbench/api/node/extHostLanguageFeatures.ts +++ b/src/vs/workbench/api/node/extHostLanguageFeatures.ts @@ -15,7 +15,7 @@ import { ExtHostDocuments } from 'vs/workbench/api/node/extHostDocuments'; import { ExtHostCommands, CommandsConverter } from 'vs/workbench/api/node/extHostCommands'; import { ExtHostDiagnostics } from 'vs/workbench/api/node/extHostDiagnostics'; import { asPromise } from 'vs/base/common/async'; -import { MainContext, MainThreadLanguageFeaturesShape, ExtHostLanguageFeaturesShape, ObjectIdentifier, IRawColorInfo, IMainContext, IdObject, ISerializedRegExp, ISerializedIndentationRule, ISerializedOnEnterRule, ISerializedLanguageConfiguration, WorkspaceSymbolDto, SuggestResultDto, WorkspaceSymbolsDto, CodeActionDto, ISerializedDocumentFilter, WorkspaceEditDto, ISerializedSignatureHelpProviderMetadata, LinkDto, CodeLensDto, MainThreadWebviewsShape, CodeInsetDto, SuggestDataDto, LinksListDto } from '../common/extHost.protocol'; +import { MainContext, MainThreadLanguageFeaturesShape, ExtHostLanguageFeaturesShape, ObjectIdentifier, IRawColorInfo, IMainContext, IdObject, ISerializedRegExp, ISerializedIndentationRule, ISerializedOnEnterRule, ISerializedLanguageConfiguration, WorkspaceSymbolDto, SuggestResultDto, WorkspaceSymbolsDto, CodeActionDto, ISerializedDocumentFilter, WorkspaceEditDto, ISerializedSignatureHelpProviderMetadata, LinkDto, CodeLensDto, MainThreadWebviewsShape, CodeInsetDto, SuggestDataDto, LinksListDto, ChainedCacheId } from '../common/extHost.protocol'; import { regExpLeadsToEndlessLoop, regExpFlags } from 'vs/base/common/strings'; import { IPosition } from 'vs/editor/common/core/position'; import { IRange, Range as EditorRange } from 'vs/editor/common/core/range'; @@ -623,8 +623,7 @@ class SuggestAdapter { private _commands: CommandsConverter; private _provider: vscode.CompletionItemProvider; - private _cache = new Map(); - private _idPool = 0; + private _cache = new Cache(); constructor(documents: ExtHostDocuments, commands: CommandsConverter, provider: vscode.CompletionItemProvider) { this._documents = documents; @@ -639,33 +638,32 @@ class SuggestAdapter { return asPromise(() => this._provider.provideCompletionItems(doc, pos, token, typeConvert.CompletionContext.to(context))).then(value => { - const _id = this._idPool++; + if (!value) { + // undefined and null are valid results + return undefined; + } + + let list = Array.isArray(value) ? new CompletionList(value) : value; + let pid: number | undefined; + + // keep result for providers that support resolving + if (SuggestAdapter.supportsResolving(this._provider)) { + pid = this._cache.add(list.items); + } // the default text edit range const wordRangeBeforePos = (doc.getWordRangeAtPosition(pos) as Range || new Range(pos, pos)) .with({ end: pos }); const result: SuggestResultDto = { - x: _id, + x: pid, b: [], a: typeConvert.Range.from(wordRangeBeforePos), + c: list.isIncomplete || undefined }; - let list: CompletionList; - if (!value) { - // undefined and null are valid results - return undefined; - - } else if (Array.isArray(value)) { - list = new CompletionList(value); - - } else { - list = value; - result.c = list.isIncomplete; - } - for (let i = 0; i < list.items.length; i++) { - const suggestion = this._convertCompletionItem2(list.items[i], pos, i, _id); + const suggestion = this._convertCompletionItem(list.items[i], pos, pid && [pid, i] || undefined); // check for bad completion item // for the converter did warn if (suggestion) { @@ -673,21 +671,17 @@ class SuggestAdapter { } } - if (SuggestAdapter.supportsResolving(this._provider)) { - this._cache.set(_id, list.items); - } - return result; }); } - resolveCompletionItem(_resource: URI, position: IPosition, id: number, pid: number, token: CancellationToken): Promise { + resolveCompletionItem(_resource: URI, position: IPosition, id: ChainedCacheId, token: CancellationToken): Promise { if (typeof this._provider.resolveCompletionItem !== 'function') { return Promise.resolve(undefined); } - const item = this._cache.has(pid) ? this._cache.get(pid)![id] : undefined; + const item = this._cache.get(...id); if (!item) { return Promise.resolve(undefined); } @@ -699,7 +693,7 @@ class SuggestAdapter { } const pos = typeConvert.Position.to(position); - return this._convertCompletionItem2(resolvedItem, pos, id, pid); + return this._convertCompletionItem(resolvedItem, pos, id); }); } @@ -707,7 +701,7 @@ class SuggestAdapter { this._cache.delete(id); } - private _convertCompletionItem2(item: vscode.CompletionItem, position: vscode.Position, id: number, pid: number): SuggestDataDto | undefined { + private _convertCompletionItem(item: vscode.CompletionItem, position: vscode.Position, id: ChainedCacheId | undefined): SuggestDataDto | undefined { if (typeof item.label !== 'string' || item.label.length === 0) { console.warn('INVALID text edit -> must have at least a label'); return undefined; @@ -716,7 +710,6 @@ class SuggestAdapter { const result: SuggestDataDto = { // x: id, - y: pid, // a: item.label, b: typeConvert.CompletionItemKind.from(item.kind), @@ -803,7 +796,7 @@ class SignatureHelpAdapter { class Cache { private _data = new Map(); - private _idPool = 0; + private _idPool = 1; add(item: T[]): number { const id = this._idPool++; @@ -856,11 +849,11 @@ class LinkProviderAdapter { }); } - resolveLink(link: LinkDto, token: CancellationToken): Promise { - if (!link.cacheId || typeof this._provider.resolveDocumentLink !== 'function') { + resolveLink(id: ChainedCacheId, token: CancellationToken): Promise { + if (typeof this._provider.resolveDocumentLink !== 'function') { return Promise.resolve(undefined); } - const item = this._cache.get(...link.cacheId); + const item = this._cache.get(...id); if (!item) { return Promise.resolve(undefined); } @@ -1402,8 +1395,8 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape { return this._withAdapter(handle, SuggestAdapter, adapter => adapter.provideCompletionItems(URI.revive(resource), position, context, token), undefined); } - $resolveCompletionItem(handle: number, resource: UriComponents, position: IPosition, id: number, pid: number, token: CancellationToken): Promise { - return this._withAdapter(handle, SuggestAdapter, adapter => adapter.resolveCompletionItem(URI.revive(resource), position, id, pid, token), undefined); + $resolveCompletionItem(handle: number, resource: UriComponents, position: IPosition, id: ChainedCacheId, token: CancellationToken): Promise { + return this._withAdapter(handle, SuggestAdapter, adapter => adapter.resolveCompletionItem(URI.revive(resource), position, id, token), undefined); } $releaseCompletionItems(handle: number, id: number): void { @@ -1438,8 +1431,8 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape { return this._withAdapter(handle, LinkProviderAdapter, adapter => adapter.provideLinks(URI.revive(resource), token), undefined); } - $resolveDocumentLink(handle: number, link: LinkDto, token: CancellationToken): Promise { - return this._withAdapter(handle, LinkProviderAdapter, adapter => adapter.resolveLink(link, token), undefined); + $resolveDocumentLink(handle: number, id: ChainedCacheId, token: CancellationToken): Promise { + return this._withAdapter(handle, LinkProviderAdapter, adapter => adapter.resolveLink(id, token), undefined); } $releaseDocumentLinks(handle: number, id: number): void {