From 54f90d6df032f3773325c27e7321bc55c40b7c93 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Mon, 22 Jul 2024 11:12:19 -0700 Subject: [PATCH] Add experimental recursive version of executeHoverProvider command (#221993) * Add test recursive version of command For #218240 Adds a `executeHoverProvider_recursive` version of the command. This avoids calling any exclusive providers Not super happy with this as it duplicates code for a very specialized use. However it does work and is considerably simpler than some of the other approaches I explored in #218240 Instead of adding duplicate commands, we could instead use an argument or somehow sneak this information in on the uri. Changing the uri is a little scary tho as we have to make sure the modified uri doesn't leak back and confuse providers * Add versions for go to commands too --- .../editor/common/languageFeatureRegistry.ts | 44 +++++++------ .../gotoSymbol/browser/goToCommands.ts | 14 ++--- .../contrib/gotoSymbol/browser/goToSymbol.ts | 62 ++++++++++++++----- .../browser/link/goToDefinitionAtPosition.ts | 2 +- .../editor/contrib/hover/browser/getHover.ts | 13 ++-- .../browser/stickyScrollController.ts | 2 +- .../api/common/extHostApiCommands.ts | 30 +++++++++ .../browser/extHostLanguageFeatures.test.ts | 20 +++--- 8 files changed, 129 insertions(+), 58 deletions(-) diff --git a/src/vs/editor/common/languageFeatureRegistry.ts b/src/vs/editor/common/languageFeatureRegistry.ts index 47679f308f475..32489739254b5 100644 --- a/src/vs/editor/common/languageFeatureRegistry.ts +++ b/src/vs/editor/common/languageFeatureRegistry.ts @@ -10,10 +10,10 @@ import { LanguageFilter, LanguageSelector, score } from 'vs/editor/common/langua import { URI } from 'vs/base/common/uri'; interface Entry { - selector: LanguageSelector; - provider: T; + readonly selector: LanguageSelector; + readonly provider: T; _score: number; - _time: number; + readonly _time: number; } function isExclusive(selector: LanguageSelector): boolean { @@ -40,14 +40,16 @@ class MatchCandidate { readonly uri: URI, readonly languageId: string, readonly notebookUri: URI | undefined, - readonly notebookType: string | undefined + readonly notebookType: string | undefined, + readonly recursive: boolean, ) { } equals(other: MatchCandidate): boolean { return this.notebookType === other.notebookType && this.languageId === other.languageId && this.uri.toString() === other.uri.toString() - && this.notebookUri?.toString() === other.notebookUri?.toString(); + && this.notebookUri?.toString() === other.notebookUri?.toString() + && this.recursive === other.recursive; } } @@ -96,7 +98,7 @@ export class LanguageFeatureRegistry { return []; } - this._updateScores(model); + this._updateScores(model, false); const result: T[] = []; // from registry @@ -113,9 +115,9 @@ export class LanguageFeatureRegistry { return this._entries.map(entry => entry.provider); } - ordered(model: ITextModel): T[] { + ordered(model: ITextModel, recursive = false): T[] { const result: T[] = []; - this._orderedForEach(model, entry => result.push(entry.provider)); + this._orderedForEach(model, recursive, entry => result.push(entry.provider)); return result; } @@ -124,7 +126,7 @@ export class LanguageFeatureRegistry { let lastBucket: T[]; let lastBucketScore: number; - this._orderedForEach(model, entry => { + this._orderedForEach(model, false, entry => { if (lastBucket && lastBucketScore === entry._score) { lastBucket.push(entry.provider); } else { @@ -137,9 +139,9 @@ export class LanguageFeatureRegistry { return result; } - private _orderedForEach(model: ITextModel, callback: (provider: Entry) => any): void { + private _orderedForEach(model: ITextModel, recursive: boolean, callback: (provider: Entry) => any): void { - this._updateScores(model); + this._updateScores(model, recursive); for (const entry of this._entries) { if (entry._score > 0) { @@ -150,15 +152,15 @@ export class LanguageFeatureRegistry { private _lastCandidate: MatchCandidate | undefined; - private _updateScores(model: ITextModel): void { + private _updateScores(model: ITextModel, recursive: boolean): void { const notebookInfo = this._notebookInfoResolver?.(model.uri); // use the uri (scheme, pattern) of the notebook info iff we have one // otherwise it's the model's/document's uri const candidate = notebookInfo - ? new MatchCandidate(model.uri, model.getLanguageId(), notebookInfo.uri, notebookInfo.type) - : new MatchCandidate(model.uri, model.getLanguageId(), undefined, undefined); + ? new MatchCandidate(model.uri, model.getLanguageId(), notebookInfo.uri, notebookInfo.type, recursive) + : new MatchCandidate(model.uri, model.getLanguageId(), undefined, undefined, recursive); if (this._lastCandidate?.equals(candidate)) { // nothing has changed @@ -171,13 +173,17 @@ export class LanguageFeatureRegistry { entry._score = score(entry.selector, candidate.uri, candidate.languageId, shouldSynchronizeModel(model), candidate.notebookUri, candidate.notebookType); if (isExclusive(entry.selector) && entry._score > 0) { - // support for one exclusive selector that overwrites - // any other selector - for (const entry of this._entries) { + if (recursive) { entry._score = 0; + } else { + // support for one exclusive selector that overwrites + // any other selector + for (const entry of this._entries) { + entry._score = 0; + } + entry._score = 1000; + break; } - entry._score = 1000; - break; } } diff --git a/src/vs/editor/contrib/gotoSymbol/browser/goToCommands.ts b/src/vs/editor/contrib/gotoSymbol/browser/goToCommands.ts index 76b08cc63c24b..63541f54790f2 100644 --- a/src/vs/editor/contrib/gotoSymbol/browser/goToCommands.ts +++ b/src/vs/editor/contrib/gotoSymbol/browser/goToCommands.ts @@ -253,7 +253,7 @@ export abstract class SymbolNavigationAction extends EditorAction2 { export class DefinitionAction extends SymbolNavigationAction { protected async _getLocationModel(languageFeaturesService: ILanguageFeaturesService, model: ITextModel, position: corePosition.Position, token: CancellationToken): Promise { - return new ReferencesModel(await getDefinitionsAtPosition(languageFeaturesService.definitionProvider, model, position, token), nls.localize('def.title', 'Definitions')); + return new ReferencesModel(await getDefinitionsAtPosition(languageFeaturesService.definitionProvider, model, position, false, token), nls.localize('def.title', 'Definitions')); } protected _getNoResultFoundMessage(info: IWordAtPosition | null): string { @@ -380,7 +380,7 @@ registerAction2(class PeekDefinitionAction extends DefinitionAction { class DeclarationAction extends SymbolNavigationAction { protected async _getLocationModel(languageFeaturesService: ILanguageFeaturesService, model: ITextModel, position: corePosition.Position, token: CancellationToken): Promise { - return new ReferencesModel(await getDeclarationsAtPosition(languageFeaturesService.declarationProvider, model, position, token), nls.localize('decl.title', 'Declarations')); + return new ReferencesModel(await getDeclarationsAtPosition(languageFeaturesService.declarationProvider, model, position, false, token), nls.localize('decl.title', 'Declarations')); } protected _getNoResultFoundMessage(info: IWordAtPosition | null): string { @@ -467,7 +467,7 @@ registerAction2(class PeekDeclarationAction extends DeclarationAction { class TypeDefinitionAction extends SymbolNavigationAction { protected async _getLocationModel(languageFeaturesService: ILanguageFeaturesService, model: ITextModel, position: corePosition.Position, token: CancellationToken): Promise { - return new ReferencesModel(await getTypeDefinitionsAtPosition(languageFeaturesService.typeDefinitionProvider, model, position, token), nls.localize('typedef.title', 'Type Definitions')); + return new ReferencesModel(await getTypeDefinitionsAtPosition(languageFeaturesService.typeDefinitionProvider, model, position, false, token), nls.localize('typedef.title', 'Type Definitions')); } protected _getNoResultFoundMessage(info: IWordAtPosition | null): string { @@ -553,7 +553,7 @@ registerAction2(class PeekTypeDefinitionAction extends TypeDefinitionAction { class ImplementationAction extends SymbolNavigationAction { protected async _getLocationModel(languageFeaturesService: ILanguageFeaturesService, model: ITextModel, position: corePosition.Position, token: CancellationToken): Promise { - return new ReferencesModel(await getImplementationsAtPosition(languageFeaturesService.implementationProvider, model, position, token), nls.localize('impl.title', 'Implementations')); + return new ReferencesModel(await getImplementationsAtPosition(languageFeaturesService.implementationProvider, model, position, false, token), nls.localize('impl.title', 'Implementations')); } protected _getNoResultFoundMessage(info: IWordAtPosition | null): string { @@ -695,7 +695,7 @@ registerAction2(class GoToReferencesAction extends ReferencesAction { } protected async _getLocationModel(languageFeaturesService: ILanguageFeaturesService, model: ITextModel, position: corePosition.Position, token: CancellationToken): Promise { - return new ReferencesModel(await getReferencesAtPosition(languageFeaturesService.referenceProvider, model, position, true, token), nls.localize('ref.title', 'References')); + return new ReferencesModel(await getReferencesAtPosition(languageFeaturesService.referenceProvider, model, position, true, false, token), nls.localize('ref.title', 'References')); } }); @@ -723,7 +723,7 @@ registerAction2(class PeekReferencesAction extends ReferencesAction { } protected async _getLocationModel(languageFeaturesService: ILanguageFeaturesService, model: ITextModel, position: corePosition.Position, token: CancellationToken): Promise { - return new ReferencesModel(await getReferencesAtPosition(languageFeaturesService.referenceProvider, model, position, false, token), nls.localize('ref.title', 'References')); + return new ReferencesModel(await getReferencesAtPosition(languageFeaturesService.referenceProvider, model, position, false, false, token), nls.localize('ref.title', 'References')); } }); @@ -846,7 +846,7 @@ CommandsRegistry.registerCommand({ return undefined; } - const references = createCancelablePromise(token => getReferencesAtPosition(languageFeaturesService.referenceProvider, control.getModel(), corePosition.Position.lift(position), false, token).then(references => new ReferencesModel(references, nls.localize('ref.title', 'References')))); + const references = createCancelablePromise(token => getReferencesAtPosition(languageFeaturesService.referenceProvider, control.getModel(), corePosition.Position.lift(position), false, false, token).then(references => new ReferencesModel(references, nls.localize('ref.title', 'References')))); const range = new Range(position.lineNumber, position.column, position.lineNumber, position.column); return Promise.resolve(controller.toggleWidget(range, references, false)); }); diff --git a/src/vs/editor/contrib/gotoSymbol/browser/goToSymbol.ts b/src/vs/editor/contrib/gotoSymbol/browser/goToSymbol.ts index 738af806684cb..93d144c77f4dd 100644 --- a/src/vs/editor/contrib/gotoSymbol/browser/goToSymbol.ts +++ b/src/vs/editor/contrib/gotoSymbol/browser/goToSymbol.ts @@ -33,9 +33,10 @@ async function getLocationLinks( model: ITextModel, position: Position, registry: LanguageFeatureRegistry, + recursive: boolean, provide: (provider: T, model: ITextModel, position: Position) => ProviderResult ): Promise { - const provider = registry.ordered(model); + const provider = registry.ordered(model, recursive); // get results const promises = provider.map((provider): Promise => { @@ -49,32 +50,32 @@ async function getLocationLinks( return coalesce(values.flat()).filter(loc => shouldIncludeLocationLink(model, loc)); } -export function getDefinitionsAtPosition(registry: LanguageFeatureRegistry, model: ITextModel, position: Position, token: CancellationToken): Promise { - return getLocationLinks(model, position, registry, (provider, model, position) => { +export function getDefinitionsAtPosition(registry: LanguageFeatureRegistry, model: ITextModel, position: Position, recursive: boolean, token: CancellationToken): Promise { + return getLocationLinks(model, position, registry, recursive, (provider, model, position) => { return provider.provideDefinition(model, position, token); }); } -export function getDeclarationsAtPosition(registry: LanguageFeatureRegistry, model: ITextModel, position: Position, token: CancellationToken): Promise { - return getLocationLinks(model, position, registry, (provider, model, position) => { +export function getDeclarationsAtPosition(registry: LanguageFeatureRegistry, model: ITextModel, position: Position, recursive: boolean, token: CancellationToken): Promise { + return getLocationLinks(model, position, registry, recursive, (provider, model, position) => { return provider.provideDeclaration(model, position, token); }); } -export function getImplementationsAtPosition(registry: LanguageFeatureRegistry, model: ITextModel, position: Position, token: CancellationToken): Promise { - return getLocationLinks(model, position, registry, (provider, model, position) => { +export function getImplementationsAtPosition(registry: LanguageFeatureRegistry, model: ITextModel, position: Position, recursive: boolean, token: CancellationToken): Promise { + return getLocationLinks(model, position, registry, recursive, (provider, model, position) => { return provider.provideImplementation(model, position, token); }); } -export function getTypeDefinitionsAtPosition(registry: LanguageFeatureRegistry, model: ITextModel, position: Position, token: CancellationToken): Promise { - return getLocationLinks(model, position, registry, (provider, model, position) => { +export function getTypeDefinitionsAtPosition(registry: LanguageFeatureRegistry, model: ITextModel, position: Position, recursive: boolean, token: CancellationToken): Promise { + return getLocationLinks(model, position, registry, recursive, (provider, model, position) => { return provider.provideTypeDefinition(model, position, token); }); } -export function getReferencesAtPosition(registry: LanguageFeatureRegistry, model: ITextModel, position: Position, compact: boolean, token: CancellationToken): Promise { - return getLocationLinks(model, position, registry, async (provider, model, position) => { +export function getReferencesAtPosition(registry: LanguageFeatureRegistry, model: ITextModel, position: Position, compact: boolean, recursive: boolean, token: CancellationToken): Promise { + return getLocationLinks(model, position, registry, recursive, async (provider, model, position) => { const result = (await provider.provideReferences(model, position, { includeDeclaration: true }, token))?.filter(ref => shouldIncludeLocationLink(model, ref)); if (!compact || !result || result.length !== 2) { return result; @@ -99,30 +100,59 @@ async function _sortedAndDeduped(callback: () => Promise): Promi registerModelAndPositionCommand('_executeDefinitionProvider', (accessor, model, position) => { const languageFeaturesService = accessor.get(ILanguageFeaturesService); - const promise = getDefinitionsAtPosition(languageFeaturesService.definitionProvider, model, position, CancellationToken.None); + const promise = getDefinitionsAtPosition(languageFeaturesService.definitionProvider, model, position, false, CancellationToken.None); + return _sortedAndDeduped(() => promise); +}); + +registerModelAndPositionCommand('_executeDefinitionProvider_recursive', (accessor, model, position) => { + const languageFeaturesService = accessor.get(ILanguageFeaturesService); + const promise = getDefinitionsAtPosition(languageFeaturesService.definitionProvider, model, position, true, CancellationToken.None); return _sortedAndDeduped(() => promise); }); registerModelAndPositionCommand('_executeTypeDefinitionProvider', (accessor, model, position) => { const languageFeaturesService = accessor.get(ILanguageFeaturesService); - const promise = getTypeDefinitionsAtPosition(languageFeaturesService.typeDefinitionProvider, model, position, CancellationToken.None); + const promise = getTypeDefinitionsAtPosition(languageFeaturesService.typeDefinitionProvider, model, position, false, CancellationToken.None); + return _sortedAndDeduped(() => promise); +}); + +registerModelAndPositionCommand('_executeTypeDefinitionProvider_recursive', (accessor, model, position) => { + const languageFeaturesService = accessor.get(ILanguageFeaturesService); + const promise = getTypeDefinitionsAtPosition(languageFeaturesService.typeDefinitionProvider, model, position, true, CancellationToken.None); return _sortedAndDeduped(() => promise); }); registerModelAndPositionCommand('_executeDeclarationProvider', (accessor, model, position) => { const languageFeaturesService = accessor.get(ILanguageFeaturesService); - const promise = getDeclarationsAtPosition(languageFeaturesService.declarationProvider, model, position, CancellationToken.None); + const promise = getDeclarationsAtPosition(languageFeaturesService.declarationProvider, model, position, false, CancellationToken.None); + return _sortedAndDeduped(() => promise); +}); +registerModelAndPositionCommand('_executeDeclarationProvider_recursive', (accessor, model, position) => { + const languageFeaturesService = accessor.get(ILanguageFeaturesService); + const promise = getDeclarationsAtPosition(languageFeaturesService.declarationProvider, model, position, true, CancellationToken.None); return _sortedAndDeduped(() => promise); }); registerModelAndPositionCommand('_executeReferenceProvider', (accessor, model, position) => { const languageFeaturesService = accessor.get(ILanguageFeaturesService); - const promise = getReferencesAtPosition(languageFeaturesService.referenceProvider, model, position, false, CancellationToken.None); + const promise = getReferencesAtPosition(languageFeaturesService.referenceProvider, model, position, false, false, CancellationToken.None); + return _sortedAndDeduped(() => promise); +}); + +registerModelAndPositionCommand('_executeReferenceProvider_recursive', (accessor, model, position) => { + const languageFeaturesService = accessor.get(ILanguageFeaturesService); + const promise = getReferencesAtPosition(languageFeaturesService.referenceProvider, model, position, false, true, CancellationToken.None); return _sortedAndDeduped(() => promise); }); registerModelAndPositionCommand('_executeImplementationProvider', (accessor, model, position) => { const languageFeaturesService = accessor.get(ILanguageFeaturesService); - const promise = getImplementationsAtPosition(languageFeaturesService.implementationProvider, model, position, CancellationToken.None); + const promise = getImplementationsAtPosition(languageFeaturesService.implementationProvider, model, position, false, CancellationToken.None); + return _sortedAndDeduped(() => promise); +}); + +registerModelAndPositionCommand('_executeImplementationProvider_recursive', (accessor, model, position) => { + const languageFeaturesService = accessor.get(ILanguageFeaturesService); + const promise = getImplementationsAtPosition(languageFeaturesService.implementationProvider, model, position, true, CancellationToken.None); return _sortedAndDeduped(() => promise); }); diff --git a/src/vs/editor/contrib/gotoSymbol/browser/link/goToDefinitionAtPosition.ts b/src/vs/editor/contrib/gotoSymbol/browser/link/goToDefinitionAtPosition.ts index f5a08f94c1eb7..097de76f71e25 100644 --- a/src/vs/editor/contrib/gotoSymbol/browser/link/goToDefinitionAtPosition.ts +++ b/src/vs/editor/contrib/gotoSymbol/browser/link/goToDefinitionAtPosition.ts @@ -297,7 +297,7 @@ export class GotoDefinitionAtPositionEditorContribution implements IEditorContri return Promise.resolve(null); } - return getDefinitionsAtPosition(this.languageFeaturesService.definitionProvider, model, position, token); + return getDefinitionsAtPosition(this.languageFeaturesService.definitionProvider, model, position, false, token); } private gotoDefinition(position: Position, openToSide: boolean): Promise { diff --git a/src/vs/editor/contrib/hover/browser/getHover.ts b/src/vs/editor/contrib/hover/browser/getHover.ts index 608f8a1dc9651..9fc1d78fb01a0 100644 --- a/src/vs/editor/contrib/hover/browser/getHover.ts +++ b/src/vs/editor/contrib/hover/browser/getHover.ts @@ -34,14 +34,14 @@ async function executeProvider(provider: HoverProvider, ordinal: number, model: return new HoverProviderResult(provider, result, ordinal); } -export function getHoverProviderResultsAsAsyncIterable(registry: LanguageFeatureRegistry, model: ITextModel, position: Position, token: CancellationToken): AsyncIterableObject { - const providers = registry.ordered(model); +export function getHoverProviderResultsAsAsyncIterable(registry: LanguageFeatureRegistry, model: ITextModel, position: Position, token: CancellationToken, recursive = false): AsyncIterableObject { + const providers = registry.ordered(model, recursive); const promises = providers.map((provider, index) => executeProvider(provider, index, model, position, token)); return AsyncIterableObject.fromPromises(promises).coalesce(); } -export function getHoversPromise(registry: LanguageFeatureRegistry, model: ITextModel, position: Position, token: CancellationToken): Promise { - return getHoverProviderResultsAsAsyncIterable(registry, model, position, token).map(item => item.hover).toPromise(); +export function getHoversPromise(registry: LanguageFeatureRegistry, model: ITextModel, position: Position, token: CancellationToken, recursive = false): Promise { + return getHoverProviderResultsAsAsyncIterable(registry, model, position, token, recursive).map(item => item.hover).toPromise(); } registerModelAndPositionCommand('_executeHoverProvider', (accessor, model, position): Promise => { @@ -49,6 +49,11 @@ registerModelAndPositionCommand('_executeHoverProvider', (accessor, model, posit return getHoversPromise(languageFeaturesService.hoverProvider, model, position, CancellationToken.None); }); +registerModelAndPositionCommand('_executeHoverProvider_recursive', (accessor, model, position): Promise => { + const languageFeaturesService = accessor.get(ILanguageFeaturesService); + return getHoversPromise(languageFeaturesService.hoverProvider, model, position, CancellationToken.None, true); +}); + function isValid(result: Hover) { const hasRange = (typeof result.range !== 'undefined'); const hasHtmlContent = typeof result.contents !== 'undefined' && result.contents && result.contents.length > 0; diff --git a/src/vs/editor/contrib/stickyScroll/browser/stickyScrollController.ts b/src/vs/editor/contrib/stickyScroll/browser/stickyScrollController.ts index 22b8c67a2942e..65824a12798fe 100644 --- a/src/vs/editor/contrib/stickyScroll/browser/stickyScrollController.ts +++ b/src/vs/editor/contrib/stickyScroll/browser/stickyScrollController.ts @@ -324,7 +324,7 @@ export class StickyScrollController extends Disposable implements IEditorContrib let currentHTMLChild: HTMLElement; - getDefinitionsAtPosition(this._languageFeaturesService.definitionProvider, this._editor.getModel(), new Position(range.startLineNumber, range.startColumn + 1), cancellationToken.token).then((candidateDefinitions => { + getDefinitionsAtPosition(this._languageFeaturesService.definitionProvider, this._editor.getModel(), new Position(range.startLineNumber, range.startColumn + 1), false, cancellationToken.token).then((candidateDefinitions => { if (cancellationToken.token.isCancellationRequested) { return; } diff --git a/src/vs/workbench/api/common/extHostApiCommands.ts b/src/vs/workbench/api/common/extHostApiCommands.ts index 5535cec05369f..6384178b82e3c 100644 --- a/src/vs/workbench/api/common/extHostApiCommands.ts +++ b/src/vs/workbench/api/common/extHostApiCommands.ts @@ -88,32 +88,62 @@ const newCommands: ApiCommand[] = [ [ApiCommandArgument.Uri, ApiCommandArgument.Position], new ApiCommandResult<(languages.Location | languages.LocationLink)[], (types.Location | vscode.LocationLink)[] | undefined>('A promise that resolves to an array of Location or LocationLink instances.', mapLocationOrLocationLink) ), + new ApiCommand( + 'vscode.experimental.executeDefinitionProvider_recursive', '_executeDefinitionProvider_recursive', 'Execute all definition providers.', + [ApiCommandArgument.Uri, ApiCommandArgument.Position], + new ApiCommandResult<(languages.Location | languages.LocationLink)[], (types.Location | vscode.LocationLink)[] | undefined>('A promise that resolves to an array of Location or LocationLink instances.', mapLocationOrLocationLink) + ), new ApiCommand( 'vscode.executeTypeDefinitionProvider', '_executeTypeDefinitionProvider', 'Execute all type definition providers.', [ApiCommandArgument.Uri, ApiCommandArgument.Position], new ApiCommandResult<(languages.Location | languages.LocationLink)[], (types.Location | vscode.LocationLink)[] | undefined>('A promise that resolves to an array of Location or LocationLink instances.', mapLocationOrLocationLink) ), + new ApiCommand( + 'vscode.experimental.executeTypeDefinitionProvider_recursive', '_executeTypeDefinitionProvider_recursive', 'Execute all type definition providers.', + [ApiCommandArgument.Uri, ApiCommandArgument.Position], + new ApiCommandResult<(languages.Location | languages.LocationLink)[], (types.Location | vscode.LocationLink)[] | undefined>('A promise that resolves to an array of Location or LocationLink instances.', mapLocationOrLocationLink) + ), new ApiCommand( 'vscode.executeDeclarationProvider', '_executeDeclarationProvider', 'Execute all declaration providers.', [ApiCommandArgument.Uri, ApiCommandArgument.Position], new ApiCommandResult<(languages.Location | languages.LocationLink)[], (types.Location | vscode.LocationLink)[] | undefined>('A promise that resolves to an array of Location or LocationLink instances.', mapLocationOrLocationLink) ), + new ApiCommand( + 'vscode.experimental.executeDeclarationProvider_recursive', '_executeDeclarationProvider_recursive', 'Execute all declaration providers.', + [ApiCommandArgument.Uri, ApiCommandArgument.Position], + new ApiCommandResult<(languages.Location | languages.LocationLink)[], (types.Location | vscode.LocationLink)[] | undefined>('A promise that resolves to an array of Location or LocationLink instances.', mapLocationOrLocationLink) + ), new ApiCommand( 'vscode.executeImplementationProvider', '_executeImplementationProvider', 'Execute all implementation providers.', [ApiCommandArgument.Uri, ApiCommandArgument.Position], new ApiCommandResult<(languages.Location | languages.LocationLink)[], (types.Location | vscode.LocationLink)[] | undefined>('A promise that resolves to an array of Location or LocationLink instances.', mapLocationOrLocationLink) ), + new ApiCommand( + 'vscode.experimental.executeImplementationProvider_recursive', '_executeImplementationProvider_recursive', 'Execute all implementation providers.', + [ApiCommandArgument.Uri, ApiCommandArgument.Position], + new ApiCommandResult<(languages.Location | languages.LocationLink)[], (types.Location | vscode.LocationLink)[] | undefined>('A promise that resolves to an array of Location or LocationLink instances.', mapLocationOrLocationLink) + ), new ApiCommand( 'vscode.executeReferenceProvider', '_executeReferenceProvider', 'Execute all reference providers.', [ApiCommandArgument.Uri, ApiCommandArgument.Position], new ApiCommandResult('A promise that resolves to an array of Location-instances.', tryMapWith(typeConverters.location.to)) ), + new ApiCommand( + 'vscode.experimental.executeReferenceProvider', '_executeReferenceProvider_recursive', 'Execute all reference providers.', + [ApiCommandArgument.Uri, ApiCommandArgument.Position], + new ApiCommandResult('A promise that resolves to an array of Location-instances.', tryMapWith(typeConverters.location.to)) + ), // -- hover new ApiCommand( 'vscode.executeHoverProvider', '_executeHoverProvider', 'Execute all hover providers.', [ApiCommandArgument.Uri, ApiCommandArgument.Position], new ApiCommandResult('A promise that resolves to an array of Hover-instances.', tryMapWith(typeConverters.Hover.to)) ), + new ApiCommand( + 'vscode.experimental.executeHoverProvider_recursive', '_executeHoverProvider_recursive', 'Execute all hover providers.', + [ApiCommandArgument.Uri, ApiCommandArgument.Position], + new ApiCommandResult('A promise that resolves to an array of Hover-instances.', tryMapWith(typeConverters.Hover.to)) + ), // -- selection range new ApiCommand( 'vscode.executeSelectionRangeProvider', '_executeSelectionRangeProvider', 'Execute selection range provider.', diff --git a/src/vs/workbench/api/test/browser/extHostLanguageFeatures.test.ts b/src/vs/workbench/api/test/browser/extHostLanguageFeatures.test.ts index 6b7de3ca7167c..141f114ebfab4 100644 --- a/src/vs/workbench/api/test/browser/extHostLanguageFeatures.test.ts +++ b/src/vs/workbench/api/test/browser/extHostLanguageFeatures.test.ts @@ -301,7 +301,7 @@ suite('ExtHostLanguageFeatures', function () { })); await rpcProtocol.sync(); - const value = await getDefinitionsAtPosition(languageFeaturesService.definitionProvider, model, new EditorPosition(1, 1), CancellationToken.None); + const value = await getDefinitionsAtPosition(languageFeaturesService.definitionProvider, model, new EditorPosition(1, 1), false, CancellationToken.None); assert.strictEqual(value.length, 1); const [entry] = value; assert.deepStrictEqual(entry.range, { startLineNumber: 2, startColumn: 3, endLineNumber: 4, endColumn: 5 }); @@ -322,7 +322,7 @@ suite('ExtHostLanguageFeatures', function () { })); await rpcProtocol.sync(); - const value = await getDefinitionsAtPosition(languageFeaturesService.definitionProvider, model, new EditorPosition(1, 1), CancellationToken.None); + const value = await getDefinitionsAtPosition(languageFeaturesService.definitionProvider, model, new EditorPosition(1, 1), false, CancellationToken.None); assert.strictEqual(value.length, 2); }); @@ -341,7 +341,7 @@ suite('ExtHostLanguageFeatures', function () { })); await rpcProtocol.sync(); - const value = await getDefinitionsAtPosition(languageFeaturesService.definitionProvider, model, new EditorPosition(1, 1), CancellationToken.None); + const value = await getDefinitionsAtPosition(languageFeaturesService.definitionProvider, model, new EditorPosition(1, 1), false, CancellationToken.None); assert.strictEqual(value.length, 2); // let [first, second] = value; assert.strictEqual(value[0].uri.authority, 'second'); @@ -362,7 +362,7 @@ suite('ExtHostLanguageFeatures', function () { })); await rpcProtocol.sync(); - const value = await getDefinitionsAtPosition(languageFeaturesService.definitionProvider, model, new EditorPosition(1, 1), CancellationToken.None); + const value = await getDefinitionsAtPosition(languageFeaturesService.definitionProvider, model, new EditorPosition(1, 1), false, CancellationToken.None); assert.strictEqual(value.length, 1); }); @@ -377,7 +377,7 @@ suite('ExtHostLanguageFeatures', function () { })); await rpcProtocol.sync(); - const value = await getDeclarationsAtPosition(languageFeaturesService.declarationProvider, model, new EditorPosition(1, 1), CancellationToken.None); + const value = await getDeclarationsAtPosition(languageFeaturesService.declarationProvider, model, new EditorPosition(1, 1), false, CancellationToken.None); assert.strictEqual(value.length, 1); const [entry] = value; assert.deepStrictEqual(entry.range, { startLineNumber: 2, startColumn: 3, endLineNumber: 4, endColumn: 5 }); @@ -395,7 +395,7 @@ suite('ExtHostLanguageFeatures', function () { })); await rpcProtocol.sync(); - const value = await getImplementationsAtPosition(languageFeaturesService.implementationProvider, model, new EditorPosition(1, 1), CancellationToken.None); + const value = await getImplementationsAtPosition(languageFeaturesService.implementationProvider, model, new EditorPosition(1, 1), false, CancellationToken.None); assert.strictEqual(value.length, 1); const [entry] = value; assert.deepStrictEqual(entry.range, { startLineNumber: 2, startColumn: 3, endLineNumber: 4, endColumn: 5 }); @@ -413,7 +413,7 @@ suite('ExtHostLanguageFeatures', function () { })); await rpcProtocol.sync(); - const value = await getTypeDefinitionsAtPosition(languageFeaturesService.typeDefinitionProvider, model, new EditorPosition(1, 1), CancellationToken.None); + const value = await getTypeDefinitionsAtPosition(languageFeaturesService.typeDefinitionProvider, model, new EditorPosition(1, 1), false, CancellationToken.None); assert.strictEqual(value.length, 1); const [entry] = value; assert.deepStrictEqual(entry.range, { startLineNumber: 2, startColumn: 3, endLineNumber: 4, endColumn: 5 }); @@ -591,7 +591,7 @@ suite('ExtHostLanguageFeatures', function () { })); await rpcProtocol.sync(); - const value = await getReferencesAtPosition(languageFeaturesService.referenceProvider, model, new EditorPosition(1, 2), false, CancellationToken.None); + const value = await getReferencesAtPosition(languageFeaturesService.referenceProvider, model, new EditorPosition(1, 2), false, false, CancellationToken.None); assert.strictEqual(value.length, 2); const [first, second] = value; assert.strictEqual(first.uri.path, '/second'); @@ -607,7 +607,7 @@ suite('ExtHostLanguageFeatures', function () { })); await rpcProtocol.sync(); - const value = await getReferencesAtPosition(languageFeaturesService.referenceProvider, model, new EditorPosition(1, 2), false, CancellationToken.None); + const value = await getReferencesAtPosition(languageFeaturesService.referenceProvider, model, new EditorPosition(1, 2), false, false, CancellationToken.None); assert.strictEqual(value.length, 1); const [item] = value; assert.deepStrictEqual(item.range, { startLineNumber: 1, startColumn: 1, endLineNumber: 1, endColumn: 1 }); @@ -628,7 +628,7 @@ suite('ExtHostLanguageFeatures', function () { })); await rpcProtocol.sync(); - const value = await getReferencesAtPosition(languageFeaturesService.referenceProvider, model, new EditorPosition(1, 2), false, CancellationToken.None); + const value = await getReferencesAtPosition(languageFeaturesService.referenceProvider, model, new EditorPosition(1, 2), false, false, CancellationToken.None); assert.strictEqual(value.length, 1); });