Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/src/vs/editor/contrib/gotoSymbol/browser/goToSymbol.ts
3296 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
6
import { coalesce } from '../../../../base/common/arrays.js';
7
import { CancellationToken } from '../../../../base/common/cancellation.js';
8
import { onUnexpectedExternalError } from '../../../../base/common/errors.js';
9
import { matchesSomeScheme, Schemas } from '../../../../base/common/network.js';
10
import { registerModelAndPositionCommand } from '../../../browser/editorExtensions.js';
11
import { Position } from '../../../common/core/position.js';
12
import { LanguageFeatureRegistry } from '../../../common/languageFeatureRegistry.js';
13
import { DeclarationProvider, DefinitionProvider, ImplementationProvider, LocationLink, ProviderResult, ReferenceProvider, TypeDefinitionProvider } from '../../../common/languages.js';
14
import { ITextModel } from '../../../common/model.js';
15
import { ILanguageFeaturesService } from '../../../common/services/languageFeatures.js';
16
import { ReferencesModel } from './referencesModel.js';
17
18
function shouldIncludeLocationLink(sourceModel: ITextModel, loc: LocationLink): boolean {
19
// Always allow the location if the request comes from a document with the same scheme.
20
if (loc.uri.scheme === sourceModel.uri.scheme) {
21
return true;
22
}
23
24
// Otherwise filter out locations from internal schemes
25
if (matchesSomeScheme(loc.uri, Schemas.walkThroughSnippet, Schemas.vscodeChatCodeBlock, Schemas.vscodeChatCodeCompareBlock)) {
26
return false;
27
}
28
29
return true;
30
}
31
32
async function getLocationLinks<T>(
33
model: ITextModel,
34
position: Position,
35
registry: LanguageFeatureRegistry<T>,
36
recursive: boolean,
37
provide: (provider: T, model: ITextModel, position: Position) => ProviderResult<LocationLink | LocationLink[]>
38
): Promise<LocationLink[]> {
39
const provider = registry.ordered(model, recursive);
40
41
// get results
42
const promises = provider.map((provider): Promise<LocationLink | LocationLink[] | undefined> => {
43
return Promise.resolve(provide(provider, model, position)).then(undefined, err => {
44
onUnexpectedExternalError(err);
45
return undefined;
46
});
47
});
48
49
const values = await Promise.all(promises);
50
return coalesce(values.flat()).filter(loc => shouldIncludeLocationLink(model, loc));
51
}
52
53
export function getDefinitionsAtPosition(registry: LanguageFeatureRegistry<DefinitionProvider>, model: ITextModel, position: Position, recursive: boolean, token: CancellationToken): Promise<LocationLink[]> {
54
return getLocationLinks(model, position, registry, recursive, (provider, model, position) => {
55
return provider.provideDefinition(model, position, token);
56
});
57
}
58
59
export function getDeclarationsAtPosition(registry: LanguageFeatureRegistry<DeclarationProvider>, model: ITextModel, position: Position, recursive: boolean, token: CancellationToken): Promise<LocationLink[]> {
60
return getLocationLinks(model, position, registry, recursive, (provider, model, position) => {
61
return provider.provideDeclaration(model, position, token);
62
});
63
}
64
65
export function getImplementationsAtPosition(registry: LanguageFeatureRegistry<ImplementationProvider>, model: ITextModel, position: Position, recursive: boolean, token: CancellationToken): Promise<LocationLink[]> {
66
return getLocationLinks(model, position, registry, recursive, (provider, model, position) => {
67
return provider.provideImplementation(model, position, token);
68
});
69
}
70
71
export function getTypeDefinitionsAtPosition(registry: LanguageFeatureRegistry<TypeDefinitionProvider>, model: ITextModel, position: Position, recursive: boolean, token: CancellationToken): Promise<LocationLink[]> {
72
return getLocationLinks(model, position, registry, recursive, (provider, model, position) => {
73
return provider.provideTypeDefinition(model, position, token);
74
});
75
}
76
77
export function getReferencesAtPosition(registry: LanguageFeatureRegistry<ReferenceProvider>, model: ITextModel, position: Position, compact: boolean, recursive: boolean, token: CancellationToken): Promise<LocationLink[]> {
78
return getLocationLinks(model, position, registry, recursive, async (provider, model, position) => {
79
const result = (await provider.provideReferences(model, position, { includeDeclaration: true }, token))?.filter(ref => shouldIncludeLocationLink(model, ref));
80
if (!compact || !result || result.length !== 2) {
81
return result;
82
}
83
const resultWithoutDeclaration = (await provider.provideReferences(model, position, { includeDeclaration: false }, token))?.filter(ref => shouldIncludeLocationLink(model, ref));
84
if (resultWithoutDeclaration && resultWithoutDeclaration.length === 1) {
85
return resultWithoutDeclaration;
86
}
87
return result;
88
});
89
}
90
91
// -- API commands ----
92
93
async function _sortedAndDeduped(callback: () => Promise<LocationLink[]>): Promise<LocationLink[]> {
94
const rawLinks = await callback();
95
const model = new ReferencesModel(rawLinks, '');
96
const modelLinks = model.references.map(ref => ref.link);
97
model.dispose();
98
return modelLinks;
99
}
100
101
registerModelAndPositionCommand('_executeDefinitionProvider', (accessor, model, position) => {
102
const languageFeaturesService = accessor.get(ILanguageFeaturesService);
103
const promise = getDefinitionsAtPosition(languageFeaturesService.definitionProvider, model, position, false, CancellationToken.None);
104
return _sortedAndDeduped(() => promise);
105
});
106
107
registerModelAndPositionCommand('_executeDefinitionProvider_recursive', (accessor, model, position) => {
108
const languageFeaturesService = accessor.get(ILanguageFeaturesService);
109
const promise = getDefinitionsAtPosition(languageFeaturesService.definitionProvider, model, position, true, CancellationToken.None);
110
return _sortedAndDeduped(() => promise);
111
});
112
113
registerModelAndPositionCommand('_executeTypeDefinitionProvider', (accessor, model, position) => {
114
const languageFeaturesService = accessor.get(ILanguageFeaturesService);
115
const promise = getTypeDefinitionsAtPosition(languageFeaturesService.typeDefinitionProvider, model, position, false, CancellationToken.None);
116
return _sortedAndDeduped(() => promise);
117
});
118
119
registerModelAndPositionCommand('_executeTypeDefinitionProvider_recursive', (accessor, model, position) => {
120
const languageFeaturesService = accessor.get(ILanguageFeaturesService);
121
const promise = getTypeDefinitionsAtPosition(languageFeaturesService.typeDefinitionProvider, model, position, true, CancellationToken.None);
122
return _sortedAndDeduped(() => promise);
123
});
124
125
registerModelAndPositionCommand('_executeDeclarationProvider', (accessor, model, position) => {
126
const languageFeaturesService = accessor.get(ILanguageFeaturesService);
127
const promise = getDeclarationsAtPosition(languageFeaturesService.declarationProvider, model, position, false, CancellationToken.None);
128
return _sortedAndDeduped(() => promise);
129
});
130
registerModelAndPositionCommand('_executeDeclarationProvider_recursive', (accessor, model, position) => {
131
const languageFeaturesService = accessor.get(ILanguageFeaturesService);
132
const promise = getDeclarationsAtPosition(languageFeaturesService.declarationProvider, model, position, true, CancellationToken.None);
133
return _sortedAndDeduped(() => promise);
134
});
135
136
registerModelAndPositionCommand('_executeReferenceProvider', (accessor, model, position) => {
137
const languageFeaturesService = accessor.get(ILanguageFeaturesService);
138
const promise = getReferencesAtPosition(languageFeaturesService.referenceProvider, model, position, false, false, CancellationToken.None);
139
return _sortedAndDeduped(() => promise);
140
});
141
142
registerModelAndPositionCommand('_executeReferenceProvider_recursive', (accessor, model, position) => {
143
const languageFeaturesService = accessor.get(ILanguageFeaturesService);
144
const promise = getReferencesAtPosition(languageFeaturesService.referenceProvider, model, position, false, true, CancellationToken.None);
145
return _sortedAndDeduped(() => promise);
146
});
147
148
registerModelAndPositionCommand('_executeImplementationProvider', (accessor, model, position) => {
149
const languageFeaturesService = accessor.get(ILanguageFeaturesService);
150
const promise = getImplementationsAtPosition(languageFeaturesService.implementationProvider, model, position, false, CancellationToken.None);
151
return _sortedAndDeduped(() => promise);
152
});
153
154
registerModelAndPositionCommand('_executeImplementationProvider_recursive', (accessor, model, position) => {
155
const languageFeaturesService = accessor.get(ILanguageFeaturesService);
156
const promise = getImplementationsAtPosition(languageFeaturesService.implementationProvider, model, position, true, CancellationToken.None);
157
return _sortedAndDeduped(() => promise);
158
});
159
160