Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/src/vs/editor/contrib/gotoSymbol/browser/peek/referencesTree.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 * as dom from '../../../../../base/browser/dom.js';
7
import { IKeyboardEvent } from '../../../../../base/browser/keyboardEvent.js';
8
import { CountBadge } from '../../../../../base/browser/ui/countBadge/countBadge.js';
9
import { HighlightedLabel } from '../../../../../base/browser/ui/highlightedlabel/highlightedLabel.js';
10
import { IconLabel } from '../../../../../base/browser/ui/iconLabel/iconLabel.js';
11
import { IIdentityProvider, IKeyboardNavigationLabelProvider, IListVirtualDelegate } from '../../../../../base/browser/ui/list/list.js';
12
import { IListAccessibilityProvider } from '../../../../../base/browser/ui/list/listWidget.js';
13
import { IAsyncDataSource, ITreeNode, ITreeRenderer } from '../../../../../base/browser/ui/tree/tree.js';
14
import { createMatches, FuzzyScore, IMatch } from '../../../../../base/common/filters.js';
15
import { Disposable } from '../../../../../base/common/lifecycle.js';
16
import { basename, dirname } from '../../../../../base/common/resources.js';
17
import { ITextModelService } from '../../../../common/services/resolverService.js';
18
import { localize } from '../../../../../nls.js';
19
import { IInstantiationService } from '../../../../../platform/instantiation/common/instantiation.js';
20
import { IKeybindingService } from '../../../../../platform/keybinding/common/keybinding.js';
21
import { ILabelService } from '../../../../../platform/label/common/label.js';
22
import { defaultCountBadgeStyles } from '../../../../../platform/theme/browser/defaultStyles.js';
23
import { FileReferences, OneReference, ReferencesModel } from '../referencesModel.js';
24
25
//#region data source
26
27
export type TreeElement = FileReferences | OneReference;
28
29
export class DataSource implements IAsyncDataSource<ReferencesModel | FileReferences, TreeElement> {
30
31
constructor(@ITextModelService private readonly _resolverService: ITextModelService) { }
32
33
hasChildren(element: ReferencesModel | FileReferences | TreeElement): boolean {
34
if (element instanceof ReferencesModel) {
35
return true;
36
}
37
if (element instanceof FileReferences) {
38
return true;
39
}
40
return false;
41
}
42
43
getChildren(element: ReferencesModel | FileReferences | TreeElement): TreeElement[] | Promise<TreeElement[]> {
44
if (element instanceof ReferencesModel) {
45
return element.groups;
46
}
47
48
if (element instanceof FileReferences) {
49
return element.resolve(this._resolverService).then(val => {
50
// if (element.failure) {
51
// // refresh the element on failure so that
52
// // we can update its rendering
53
// return tree.refresh(element).then(() => val.children);
54
// }
55
return val.children;
56
});
57
}
58
59
throw new Error('bad tree');
60
}
61
}
62
63
//#endregion
64
65
export class Delegate implements IListVirtualDelegate<TreeElement> {
66
getHeight(): number {
67
return 23;
68
}
69
getTemplateId(element: FileReferences | OneReference): string {
70
if (element instanceof FileReferences) {
71
return FileReferencesRenderer.id;
72
} else {
73
return OneReferenceRenderer.id;
74
}
75
}
76
}
77
78
export class StringRepresentationProvider implements IKeyboardNavigationLabelProvider<TreeElement> {
79
80
constructor(@IKeybindingService private readonly _keybindingService: IKeybindingService) { }
81
82
getKeyboardNavigationLabel(element: TreeElement): { toString(): string } {
83
if (element instanceof OneReference) {
84
const parts = element.parent.getPreview(element)?.preview(element.range);
85
if (parts) {
86
return parts.value;
87
}
88
}
89
// FileReferences or unresolved OneReference
90
return basename(element.uri);
91
}
92
93
mightProducePrintableCharacter(event: IKeyboardEvent): boolean {
94
return this._keybindingService.mightProducePrintableCharacter(event);
95
}
96
}
97
98
export class IdentityProvider implements IIdentityProvider<TreeElement> {
99
100
getId(element: TreeElement): { toString(): string } {
101
return element instanceof OneReference ? element.id : element.uri;
102
}
103
}
104
105
//#region render: File
106
107
class FileReferencesTemplate extends Disposable {
108
109
readonly file: IconLabel;
110
readonly badge: CountBadge;
111
112
constructor(
113
container: HTMLElement,
114
@ILabelService private readonly _labelService: ILabelService
115
) {
116
super();
117
const parent = document.createElement('div');
118
parent.classList.add('reference-file');
119
this.file = this._register(new IconLabel(parent, { supportHighlights: true }));
120
121
this.badge = this._register(new CountBadge(dom.append(parent, dom.$('.count')), {}, defaultCountBadgeStyles));
122
123
container.appendChild(parent);
124
}
125
126
set(element: FileReferences, matches: IMatch[]) {
127
const parent = dirname(element.uri);
128
this.file.setLabel(
129
this._labelService.getUriBasenameLabel(element.uri),
130
this._labelService.getUriLabel(parent, { relative: true }),
131
{ title: this._labelService.getUriLabel(element.uri), matches }
132
);
133
const len = element.children.length;
134
this.badge.setCount(len);
135
if (len > 1) {
136
this.badge.setTitleFormat(localize('referencesCount', "{0} references", len));
137
} else {
138
this.badge.setTitleFormat(localize('referenceCount', "{0} reference", len));
139
}
140
}
141
}
142
143
export class FileReferencesRenderer implements ITreeRenderer<FileReferences, FuzzyScore, FileReferencesTemplate> {
144
145
static readonly id = 'FileReferencesRenderer';
146
147
readonly templateId: string = FileReferencesRenderer.id;
148
149
constructor(@IInstantiationService private readonly _instantiationService: IInstantiationService) { }
150
151
renderTemplate(container: HTMLElement): FileReferencesTemplate {
152
return this._instantiationService.createInstance(FileReferencesTemplate, container);
153
}
154
renderElement(node: ITreeNode<FileReferences, FuzzyScore>, index: number, template: FileReferencesTemplate): void {
155
template.set(node.element, createMatches(node.filterData));
156
}
157
disposeTemplate(templateData: FileReferencesTemplate): void {
158
templateData.dispose();
159
}
160
}
161
162
//#endregion
163
164
//#region render: Reference
165
class OneReferenceTemplate extends Disposable {
166
167
readonly label: HighlightedLabel;
168
169
constructor(container: HTMLElement) {
170
super();
171
172
this.label = this._register(new HighlightedLabel(container));
173
}
174
175
set(element: OneReference, score?: FuzzyScore): void {
176
const preview = element.parent.getPreview(element)?.preview(element.range);
177
if (!preview || !preview.value) {
178
// this means we FAILED to resolve the document or the value is the empty string
179
this.label.set(`${basename(element.uri)}:${element.range.startLineNumber + 1}:${element.range.startColumn + 1}`);
180
} else {
181
// render search match as highlight unless
182
// we have score, then render the score
183
const { value, highlight } = preview;
184
if (score && !FuzzyScore.isDefault(score)) {
185
this.label.element.classList.toggle('referenceMatch', false);
186
this.label.set(value, createMatches(score));
187
} else {
188
this.label.element.classList.toggle('referenceMatch', true);
189
this.label.set(value, [highlight]);
190
}
191
}
192
}
193
}
194
195
export class OneReferenceRenderer implements ITreeRenderer<OneReference, FuzzyScore, OneReferenceTemplate> {
196
197
static readonly id = 'OneReferenceRenderer';
198
199
readonly templateId: string = OneReferenceRenderer.id;
200
201
renderTemplate(container: HTMLElement): OneReferenceTemplate {
202
return new OneReferenceTemplate(container);
203
}
204
renderElement(node: ITreeNode<OneReference, FuzzyScore>, index: number, templateData: OneReferenceTemplate): void {
205
templateData.set(node.element, node.filterData);
206
}
207
disposeTemplate(templateData: OneReferenceTemplate): void {
208
templateData.dispose();
209
}
210
}
211
212
//#endregion
213
214
215
export class AccessibilityProvider implements IListAccessibilityProvider<FileReferences | OneReference> {
216
217
getWidgetAriaLabel(): string {
218
return localize('treeAriaLabel', "References");
219
}
220
221
getAriaLabel(element: FileReferences | OneReference): string | null {
222
return element.ariaMessage;
223
}
224
}
225
226