Path: blob/main/src/vs/editor/contrib/gotoSymbol/browser/goToSymbol.ts
3296 views
/*---------------------------------------------------------------------------------------------1* Copyright (c) Microsoft Corporation. All rights reserved.2* Licensed under the MIT License. See License.txt in the project root for license information.3*--------------------------------------------------------------------------------------------*/45import { coalesce } from '../../../../base/common/arrays.js';6import { CancellationToken } from '../../../../base/common/cancellation.js';7import { onUnexpectedExternalError } from '../../../../base/common/errors.js';8import { matchesSomeScheme, Schemas } from '../../../../base/common/network.js';9import { registerModelAndPositionCommand } from '../../../browser/editorExtensions.js';10import { Position } from '../../../common/core/position.js';11import { LanguageFeatureRegistry } from '../../../common/languageFeatureRegistry.js';12import { DeclarationProvider, DefinitionProvider, ImplementationProvider, LocationLink, ProviderResult, ReferenceProvider, TypeDefinitionProvider } from '../../../common/languages.js';13import { ITextModel } from '../../../common/model.js';14import { ILanguageFeaturesService } from '../../../common/services/languageFeatures.js';15import { ReferencesModel } from './referencesModel.js';1617function shouldIncludeLocationLink(sourceModel: ITextModel, loc: LocationLink): boolean {18// Always allow the location if the request comes from a document with the same scheme.19if (loc.uri.scheme === sourceModel.uri.scheme) {20return true;21}2223// Otherwise filter out locations from internal schemes24if (matchesSomeScheme(loc.uri, Schemas.walkThroughSnippet, Schemas.vscodeChatCodeBlock, Schemas.vscodeChatCodeCompareBlock)) {25return false;26}2728return true;29}3031async function getLocationLinks<T>(32model: ITextModel,33position: Position,34registry: LanguageFeatureRegistry<T>,35recursive: boolean,36provide: (provider: T, model: ITextModel, position: Position) => ProviderResult<LocationLink | LocationLink[]>37): Promise<LocationLink[]> {38const provider = registry.ordered(model, recursive);3940// get results41const promises = provider.map((provider): Promise<LocationLink | LocationLink[] | undefined> => {42return Promise.resolve(provide(provider, model, position)).then(undefined, err => {43onUnexpectedExternalError(err);44return undefined;45});46});4748const values = await Promise.all(promises);49return coalesce(values.flat()).filter(loc => shouldIncludeLocationLink(model, loc));50}5152export function getDefinitionsAtPosition(registry: LanguageFeatureRegistry<DefinitionProvider>, model: ITextModel, position: Position, recursive: boolean, token: CancellationToken): Promise<LocationLink[]> {53return getLocationLinks(model, position, registry, recursive, (provider, model, position) => {54return provider.provideDefinition(model, position, token);55});56}5758export function getDeclarationsAtPosition(registry: LanguageFeatureRegistry<DeclarationProvider>, model: ITextModel, position: Position, recursive: boolean, token: CancellationToken): Promise<LocationLink[]> {59return getLocationLinks(model, position, registry, recursive, (provider, model, position) => {60return provider.provideDeclaration(model, position, token);61});62}6364export function getImplementationsAtPosition(registry: LanguageFeatureRegistry<ImplementationProvider>, model: ITextModel, position: Position, recursive: boolean, token: CancellationToken): Promise<LocationLink[]> {65return getLocationLinks(model, position, registry, recursive, (provider, model, position) => {66return provider.provideImplementation(model, position, token);67});68}6970export function getTypeDefinitionsAtPosition(registry: LanguageFeatureRegistry<TypeDefinitionProvider>, model: ITextModel, position: Position, recursive: boolean, token: CancellationToken): Promise<LocationLink[]> {71return getLocationLinks(model, position, registry, recursive, (provider, model, position) => {72return provider.provideTypeDefinition(model, position, token);73});74}7576export function getReferencesAtPosition(registry: LanguageFeatureRegistry<ReferenceProvider>, model: ITextModel, position: Position, compact: boolean, recursive: boolean, token: CancellationToken): Promise<LocationLink[]> {77return getLocationLinks(model, position, registry, recursive, async (provider, model, position) => {78const result = (await provider.provideReferences(model, position, { includeDeclaration: true }, token))?.filter(ref => shouldIncludeLocationLink(model, ref));79if (!compact || !result || result.length !== 2) {80return result;81}82const resultWithoutDeclaration = (await provider.provideReferences(model, position, { includeDeclaration: false }, token))?.filter(ref => shouldIncludeLocationLink(model, ref));83if (resultWithoutDeclaration && resultWithoutDeclaration.length === 1) {84return resultWithoutDeclaration;85}86return result;87});88}8990// -- API commands ----9192async function _sortedAndDeduped(callback: () => Promise<LocationLink[]>): Promise<LocationLink[]> {93const rawLinks = await callback();94const model = new ReferencesModel(rawLinks, '');95const modelLinks = model.references.map(ref => ref.link);96model.dispose();97return modelLinks;98}99100registerModelAndPositionCommand('_executeDefinitionProvider', (accessor, model, position) => {101const languageFeaturesService = accessor.get(ILanguageFeaturesService);102const promise = getDefinitionsAtPosition(languageFeaturesService.definitionProvider, model, position, false, CancellationToken.None);103return _sortedAndDeduped(() => promise);104});105106registerModelAndPositionCommand('_executeDefinitionProvider_recursive', (accessor, model, position) => {107const languageFeaturesService = accessor.get(ILanguageFeaturesService);108const promise = getDefinitionsAtPosition(languageFeaturesService.definitionProvider, model, position, true, CancellationToken.None);109return _sortedAndDeduped(() => promise);110});111112registerModelAndPositionCommand('_executeTypeDefinitionProvider', (accessor, model, position) => {113const languageFeaturesService = accessor.get(ILanguageFeaturesService);114const promise = getTypeDefinitionsAtPosition(languageFeaturesService.typeDefinitionProvider, model, position, false, CancellationToken.None);115return _sortedAndDeduped(() => promise);116});117118registerModelAndPositionCommand('_executeTypeDefinitionProvider_recursive', (accessor, model, position) => {119const languageFeaturesService = accessor.get(ILanguageFeaturesService);120const promise = getTypeDefinitionsAtPosition(languageFeaturesService.typeDefinitionProvider, model, position, true, CancellationToken.None);121return _sortedAndDeduped(() => promise);122});123124registerModelAndPositionCommand('_executeDeclarationProvider', (accessor, model, position) => {125const languageFeaturesService = accessor.get(ILanguageFeaturesService);126const promise = getDeclarationsAtPosition(languageFeaturesService.declarationProvider, model, position, false, CancellationToken.None);127return _sortedAndDeduped(() => promise);128});129registerModelAndPositionCommand('_executeDeclarationProvider_recursive', (accessor, model, position) => {130const languageFeaturesService = accessor.get(ILanguageFeaturesService);131const promise = getDeclarationsAtPosition(languageFeaturesService.declarationProvider, model, position, true, CancellationToken.None);132return _sortedAndDeduped(() => promise);133});134135registerModelAndPositionCommand('_executeReferenceProvider', (accessor, model, position) => {136const languageFeaturesService = accessor.get(ILanguageFeaturesService);137const promise = getReferencesAtPosition(languageFeaturesService.referenceProvider, model, position, false, false, CancellationToken.None);138return _sortedAndDeduped(() => promise);139});140141registerModelAndPositionCommand('_executeReferenceProvider_recursive', (accessor, model, position) => {142const languageFeaturesService = accessor.get(ILanguageFeaturesService);143const promise = getReferencesAtPosition(languageFeaturesService.referenceProvider, model, position, false, true, CancellationToken.None);144return _sortedAndDeduped(() => promise);145});146147registerModelAndPositionCommand('_executeImplementationProvider', (accessor, model, position) => {148const languageFeaturesService = accessor.get(ILanguageFeaturesService);149const promise = getImplementationsAtPosition(languageFeaturesService.implementationProvider, model, position, false, CancellationToken.None);150return _sortedAndDeduped(() => promise);151});152153registerModelAndPositionCommand('_executeImplementationProvider_recursive', (accessor, model, position) => {154const languageFeaturesService = accessor.get(ILanguageFeaturesService);155const promise = getImplementationsAtPosition(languageFeaturesService.implementationProvider, model, position, true, CancellationToken.None);156return _sortedAndDeduped(() => promise);157});158159160