Path: blob/main/src/vs/editor/contrib/gotoSymbol/browser/peek/referencesTree.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 * as dom from '../../../../../base/browser/dom.js';6import { IKeyboardEvent } from '../../../../../base/browser/keyboardEvent.js';7import { CountBadge } from '../../../../../base/browser/ui/countBadge/countBadge.js';8import { HighlightedLabel } from '../../../../../base/browser/ui/highlightedlabel/highlightedLabel.js';9import { IconLabel } from '../../../../../base/browser/ui/iconLabel/iconLabel.js';10import { IIdentityProvider, IKeyboardNavigationLabelProvider, IListVirtualDelegate } from '../../../../../base/browser/ui/list/list.js';11import { IListAccessibilityProvider } from '../../../../../base/browser/ui/list/listWidget.js';12import { IAsyncDataSource, ITreeNode, ITreeRenderer } from '../../../../../base/browser/ui/tree/tree.js';13import { createMatches, FuzzyScore, IMatch } from '../../../../../base/common/filters.js';14import { Disposable } from '../../../../../base/common/lifecycle.js';15import { basename, dirname } from '../../../../../base/common/resources.js';16import { ITextModelService } from '../../../../common/services/resolverService.js';17import { localize } from '../../../../../nls.js';18import { IInstantiationService } from '../../../../../platform/instantiation/common/instantiation.js';19import { IKeybindingService } from '../../../../../platform/keybinding/common/keybinding.js';20import { ILabelService } from '../../../../../platform/label/common/label.js';21import { defaultCountBadgeStyles } from '../../../../../platform/theme/browser/defaultStyles.js';22import { FileReferences, OneReference, ReferencesModel } from '../referencesModel.js';2324//#region data source2526export type TreeElement = FileReferences | OneReference;2728export class DataSource implements IAsyncDataSource<ReferencesModel | FileReferences, TreeElement> {2930constructor(@ITextModelService private readonly _resolverService: ITextModelService) { }3132hasChildren(element: ReferencesModel | FileReferences | TreeElement): boolean {33if (element instanceof ReferencesModel) {34return true;35}36if (element instanceof FileReferences) {37return true;38}39return false;40}4142getChildren(element: ReferencesModel | FileReferences | TreeElement): TreeElement[] | Promise<TreeElement[]> {43if (element instanceof ReferencesModel) {44return element.groups;45}4647if (element instanceof FileReferences) {48return element.resolve(this._resolverService).then(val => {49// if (element.failure) {50// // refresh the element on failure so that51// // we can update its rendering52// return tree.refresh(element).then(() => val.children);53// }54return val.children;55});56}5758throw new Error('bad tree');59}60}6162//#endregion6364export class Delegate implements IListVirtualDelegate<TreeElement> {65getHeight(): number {66return 23;67}68getTemplateId(element: FileReferences | OneReference): string {69if (element instanceof FileReferences) {70return FileReferencesRenderer.id;71} else {72return OneReferenceRenderer.id;73}74}75}7677export class StringRepresentationProvider implements IKeyboardNavigationLabelProvider<TreeElement> {7879constructor(@IKeybindingService private readonly _keybindingService: IKeybindingService) { }8081getKeyboardNavigationLabel(element: TreeElement): { toString(): string } {82if (element instanceof OneReference) {83const parts = element.parent.getPreview(element)?.preview(element.range);84if (parts) {85return parts.value;86}87}88// FileReferences or unresolved OneReference89return basename(element.uri);90}9192mightProducePrintableCharacter(event: IKeyboardEvent): boolean {93return this._keybindingService.mightProducePrintableCharacter(event);94}95}9697export class IdentityProvider implements IIdentityProvider<TreeElement> {9899getId(element: TreeElement): { toString(): string } {100return element instanceof OneReference ? element.id : element.uri;101}102}103104//#region render: File105106class FileReferencesTemplate extends Disposable {107108readonly file: IconLabel;109readonly badge: CountBadge;110111constructor(112container: HTMLElement,113@ILabelService private readonly _labelService: ILabelService114) {115super();116const parent = document.createElement('div');117parent.classList.add('reference-file');118this.file = this._register(new IconLabel(parent, { supportHighlights: true }));119120this.badge = this._register(new CountBadge(dom.append(parent, dom.$('.count')), {}, defaultCountBadgeStyles));121122container.appendChild(parent);123}124125set(element: FileReferences, matches: IMatch[]) {126const parent = dirname(element.uri);127this.file.setLabel(128this._labelService.getUriBasenameLabel(element.uri),129this._labelService.getUriLabel(parent, { relative: true }),130{ title: this._labelService.getUriLabel(element.uri), matches }131);132const len = element.children.length;133this.badge.setCount(len);134if (len > 1) {135this.badge.setTitleFormat(localize('referencesCount', "{0} references", len));136} else {137this.badge.setTitleFormat(localize('referenceCount', "{0} reference", len));138}139}140}141142export class FileReferencesRenderer implements ITreeRenderer<FileReferences, FuzzyScore, FileReferencesTemplate> {143144static readonly id = 'FileReferencesRenderer';145146readonly templateId: string = FileReferencesRenderer.id;147148constructor(@IInstantiationService private readonly _instantiationService: IInstantiationService) { }149150renderTemplate(container: HTMLElement): FileReferencesTemplate {151return this._instantiationService.createInstance(FileReferencesTemplate, container);152}153renderElement(node: ITreeNode<FileReferences, FuzzyScore>, index: number, template: FileReferencesTemplate): void {154template.set(node.element, createMatches(node.filterData));155}156disposeTemplate(templateData: FileReferencesTemplate): void {157templateData.dispose();158}159}160161//#endregion162163//#region render: Reference164class OneReferenceTemplate extends Disposable {165166readonly label: HighlightedLabel;167168constructor(container: HTMLElement) {169super();170171this.label = this._register(new HighlightedLabel(container));172}173174set(element: OneReference, score?: FuzzyScore): void {175const preview = element.parent.getPreview(element)?.preview(element.range);176if (!preview || !preview.value) {177// this means we FAILED to resolve the document or the value is the empty string178this.label.set(`${basename(element.uri)}:${element.range.startLineNumber + 1}:${element.range.startColumn + 1}`);179} else {180// render search match as highlight unless181// we have score, then render the score182const { value, highlight } = preview;183if (score && !FuzzyScore.isDefault(score)) {184this.label.element.classList.toggle('referenceMatch', false);185this.label.set(value, createMatches(score));186} else {187this.label.element.classList.toggle('referenceMatch', true);188this.label.set(value, [highlight]);189}190}191}192}193194export class OneReferenceRenderer implements ITreeRenderer<OneReference, FuzzyScore, OneReferenceTemplate> {195196static readonly id = 'OneReferenceRenderer';197198readonly templateId: string = OneReferenceRenderer.id;199200renderTemplate(container: HTMLElement): OneReferenceTemplate {201return new OneReferenceTemplate(container);202}203renderElement(node: ITreeNode<OneReference, FuzzyScore>, index: number, templateData: OneReferenceTemplate): void {204templateData.set(node.element, node.filterData);205}206disposeTemplate(templateData: OneReferenceTemplate): void {207templateData.dispose();208}209}210211//#endregion212213214export class AccessibilityProvider implements IListAccessibilityProvider<FileReferences | OneReference> {215216getWidgetAriaLabel(): string {217return localize('treeAriaLabel', "References");218}219220getAriaLabel(element: FileReferences | OneReference): string | null {221return element.ariaMessage;222}223}224225226