diff --git a/src/vs/editor/common/modes.ts b/src/vs/editor/common/modes.ts index 60957f38d69..b7ba9581fba 100644 --- a/src/vs/editor/common/modes.ts +++ b/src/vs/editor/common/modes.ts @@ -608,7 +608,7 @@ export interface CompletionItemProvider { * * The editor will only resolve a completion item once. */ - resolveCompletionItem?(model: model.ITextModel, position: Position, item: CompletionItem, token: CancellationToken): ProviderResult; + resolveCompletionItem?(item: CompletionItem, token: CancellationToken): ProviderResult; } export interface CodeAction { diff --git a/src/vs/editor/contrib/suggest/suggest.ts b/src/vs/editor/contrib/suggest/suggest.ts index 1f095dce778..a5d89b53ce8 100644 --- a/src/vs/editor/contrib/suggest/suggest.ts +++ b/src/vs/editor/contrib/suggest/suggest.ts @@ -33,12 +33,6 @@ export class CompletionItem { _brand!: 'ISuggestionItem'; - private static readonly _defaultResolve = () => Promise.resolve(); - - readonly resolve: (token: CancellationToken) => Promise; - isResolved: boolean = false; - - // readonly editStart: IPosition; readonly editInsertEnd: IPosition; @@ -104,36 +98,36 @@ export class CompletionItem { } // create the suggestion resolver - const { resolveCompletionItem } = provider; - if (typeof resolveCompletionItem !== 'function') { - this.resolve = CompletionItem._defaultResolve; - this.isResolved = true; - } else { - let cached: Promise | undefined; - this.resolve = (token) => { - if (!cached) { - cached = Promise.resolve(resolveCompletionItem.call(provider, model, Position.lift(position), completion, token)).then(value => { - Object.assign(completion, value); - this.isResolved = true; - }, err => { - if (isPromiseCanceledError(err)) { - // the IPC queue will reject the request with the - // cancellation error -> reset cached - cached = undefined; - } - }); - token.onCancellationRequested(() => { - if (!this.isResolved) { - // cancellation after the request has been - // dispatched -> reset cache - cached = undefined; - } - }); - } - return cached; - }; + if (typeof provider.resolveCompletionItem !== 'function') { + this._resolveCache = Promise.resolve(); } } + + // resolving + get isResolved() { + return Boolean(this._resolveCache); + } + + private _resolveCache?: Promise; + + async resolve(token: CancellationToken) { + if (!this._resolveCache) { + const sub = token.onCancellationRequested(() => { + this._resolveCache = undefined; + }); + this._resolveCache = Promise.resolve(this.provider.resolveCompletionItem!(this.completion, token)).then(value => { + Object.assign(this.completion, value); + sub.dispose(); + }, err => { + if (isPromiseCanceledError(err)) { + // the IPC queue will reject the request with the + // cancellation error -> reset cached + this._resolveCache = undefined; + } + }); + } + return this._resolveCache; + } } export const enum SnippetSortOrder { diff --git a/src/vs/monaco.d.ts b/src/vs/monaco.d.ts index bafff136680..470d73c55b2 100644 --- a/src/vs/monaco.d.ts +++ b/src/vs/monaco.d.ts @@ -5586,7 +5586,7 @@ declare namespace monaco.languages { * * The editor will only resolve a completion item once. */ - resolveCompletionItem?(model: editor.ITextModel, position: Position, item: CompletionItem, token: CancellationToken): ProviderResult; + resolveCompletionItem?(item: CompletionItem, token: CancellationToken): ProviderResult; } export interface CodeAction { diff --git a/src/vs/workbench/api/browser/mainThreadLanguageFeatures.ts b/src/vs/workbench/api/browser/mainThreadLanguageFeatures.ts index cb72f4d409e..f7195eaa219 100644 --- a/src/vs/workbench/api/browser/mainThreadLanguageFeatures.ts +++ b/src/vs/workbench/api/browser/mainThreadLanguageFeatures.ts @@ -447,8 +447,8 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha } }; if (supportsResolveDetails) { - provider.resolveCompletionItem = (model, position, suggestion, token) => { - return this._proxy.$resolveCompletionItem(handle, model.uri, position, suggestion._id!, token).then(result => { + provider.resolveCompletionItem = (suggestion, token) => { + return this._proxy.$resolveCompletionItem(handle, suggestion._id!, token).then(result => { if (!result) { return suggestion; } diff --git a/src/vs/workbench/api/common/extHost.protocol.ts b/src/vs/workbench/api/common/extHost.protocol.ts index 7e1233484e8..c2c9ccf4c2a 100644 --- a/src/vs/workbench/api/common/extHost.protocol.ts +++ b/src/vs/workbench/api/common/extHost.protocol.ts @@ -1313,7 +1313,7 @@ export interface ExtHostLanguageFeaturesShape { $releaseDocumentSemanticTokens(handle: number, semanticColoringResultId: number): void; $provideDocumentRangeSemanticTokens(handle: number, resource: UriComponents, range: IRange, token: CancellationToken): Promise; $provideCompletionItems(handle: number, resource: UriComponents, position: IPosition, context: modes.CompletionContext, token: CancellationToken): Promise; - $resolveCompletionItem(handle: number, resource: UriComponents, position: IPosition, id: ChainedCacheId, token: CancellationToken): Promise; + $resolveCompletionItem(handle: number, id: ChainedCacheId, token: CancellationToken): Promise; $releaseCompletionItems(handle: number, id: number): void; $provideSignatureHelp(handle: number, resource: UriComponents, position: IPosition, context: modes.SignatureHelpContext, token: CancellationToken): Promise; $releaseSignatureHelp(handle: number, id: number): void; diff --git a/src/vs/workbench/api/common/extHostLanguageFeatures.ts b/src/vs/workbench/api/common/extHostLanguageFeatures.ts index a87b1012e84..d2716c8c78d 100644 --- a/src/vs/workbench/api/common/extHostLanguageFeatures.ts +++ b/src/vs/workbench/api/common/extHostLanguageFeatures.ts @@ -883,7 +883,7 @@ class SuggestAdapter { return result; } - async resolveCompletionItem(_resource: URI, _position: IPosition, id: extHostProtocol.ChainedCacheId, token: CancellationToken): Promise { + async resolveCompletionItem(id: extHostProtocol.ChainedCacheId, token: CancellationToken): Promise { if (typeof this._provider.resolveCompletionItem !== 'function') { return undefined; @@ -1753,8 +1753,8 @@ export class ExtHostLanguageFeatures implements extHostProtocol.ExtHostLanguageF return this._withAdapter(handle, SuggestAdapter, adapter => adapter.provideCompletionItems(URI.revive(resource), position, context, token), undefined); } - $resolveCompletionItem(handle: number, resource: UriComponents, position: IPosition, id: extHostProtocol.ChainedCacheId, token: CancellationToken): Promise { - return this._withAdapter(handle, SuggestAdapter, adapter => adapter.resolveCompletionItem(URI.revive(resource), position, id, token), undefined); + $resolveCompletionItem(handle: number, id: extHostProtocol.ChainedCacheId, token: CancellationToken): Promise { + return this._withAdapter(handle, SuggestAdapter, adapter => adapter.resolveCompletionItem(id, token), undefined); } $releaseCompletionItems(handle: number, id: number): void { diff --git a/src/vs/workbench/contrib/snippets/browser/snippetCompletionProvider.ts b/src/vs/workbench/contrib/snippets/browser/snippetCompletionProvider.ts index e9a0b7e5388..8bb1ad640f4 100644 --- a/src/vs/workbench/contrib/snippets/browser/snippetCompletionProvider.ts +++ b/src/vs/workbench/contrib/snippets/browser/snippetCompletionProvider.ts @@ -144,7 +144,7 @@ export class SnippetCompletionProvider implements CompletionItemProvider { return { suggestions }; } - resolveCompletionItem(_model: ITextModel, _position: Position, item: CompletionItem): CompletionItem { + resolveCompletionItem(item: CompletionItem): CompletionItem { return (item instanceof SnippetCompletion) ? item.resolve() : item; }