callHierarchyTree.ts 4.0 KB
Newer Older
J
Johannes Rieken 已提交
1 2 3 4 5 6
/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/

import { IAsyncDataSource, ITreeRenderer, ITreeNode } from 'vs/base/browser/ui/tree/tree';
7
import { CallHierarchyItem, CallHierarchyDirection, CallHierarchyModel, } from 'vs/workbench/contrib/callHierarchy/browser/callHierarchy';
J
Johannes Rieken 已提交
8 9 10 11
import { CancellationToken } from 'vs/base/common/cancellation';
import { IIdentityProvider, IListVirtualDelegate } from 'vs/base/browser/ui/list/list';
import { FuzzyScore, createMatches } from 'vs/base/common/filters';
import { IconLabel } from 'vs/base/browser/ui/iconLabel/iconLabel';
12
import { SymbolKinds, Location } from 'vs/editor/common/modes';
13
import * as dom from 'vs/base/browser/dom';
J
Johannes Rieken 已提交
14 15 16 17

export class Call {
	constructor(
		readonly item: CallHierarchyItem,
J
Johannes Rieken 已提交
18
		readonly locations: Location[],
19
		readonly model: CallHierarchyModel
J
Johannes Rieken 已提交
20 21 22
	) { }
}

23
export class DataSource implements IAsyncDataSource<CallHierarchyModel, Call> {
J
Johannes Rieken 已提交
24 25

	constructor(
26
		public getDirection: () => CallHierarchyDirection,
J
Johannes Rieken 已提交
27 28
	) { }

29
	hasChildren(): boolean {
J
Johannes Rieken 已提交
30 31 32
		return true;
	}

33 34 35 36
	async getChildren(element: CallHierarchyModel | Call): Promise<Call[]> {
		if (element instanceof CallHierarchyModel) {
			return [new Call(element.root, [], element)];
		}
37 38

		const results: Call[] = [];
39 40
		if (this.getDirection() === CallHierarchyDirection.CallsFrom) {
			await this._getOutgoingCalls(element.model, element.item, results);
41
		} else {
42
			await this._getIncomingCalls(element.model, element.item, results);
J
Johannes Rieken 已提交
43
		}
44
		return results;
J
Johannes Rieken 已提交
45
	}
J
jrieken 已提交
46

47 48 49
	private async _getOutgoingCalls(model: CallHierarchyModel, item: CallHierarchyItem, bucket: Call[]): Promise<void> {

		const outgoingCalls = await model.resolveOutgoingCalls(item, CancellationToken.None);
J
jrieken 已提交
50 51
		for (const call of outgoingCalls) {
			bucket.push(new Call(
52
				call.to,
53 54
				call.fromRanges.map(range => ({ range, uri: item.uri })),
				model
J
jrieken 已提交
55
			));
J
jrieken 已提交
56 57 58
		}
	}

59 60
	private async _getIncomingCalls(model: CallHierarchyModel, item: CallHierarchyItem, bucket: Call[]): Promise<void> {
		const incomingCalls = await model.resolveIncomingCalls(item, CancellationToken.None);
J
jrieken 已提交
61 62
		for (const call of incomingCalls) {
			bucket.push(new Call(
63 64
				call.from,
				call.fromRanges.map(range => ({ range, uri: call.from.uri })),
65
				model
J
jrieken 已提交
66
			));
J
jrieken 已提交
67 68 69
		}
	}

J
Johannes Rieken 已提交
70 71
}

72

J
Johannes Rieken 已提交
73
export class IdentityProvider implements IIdentityProvider<Call> {
74 75 76 77 78

	constructor(
		public getDirection: () => CallHierarchyDirection
	) { }

J
Johannes Rieken 已提交
79
	getId(element: Call): { toString(): string; } {
80
		return this.getDirection() + '->' + element.item.id;
J
Johannes Rieken 已提交
81 82 83 84
	}
}

class CallRenderingTemplate {
J
Johannes Rieken 已提交
85
	constructor(
86 87
		readonly icon: HTMLDivElement,
		readonly label: IconLabel
J
Johannes Rieken 已提交
88
	) { }
J
Johannes Rieken 已提交
89 90 91 92
}

export class CallRenderer implements ITreeRenderer<Call, FuzzyScore, CallRenderingTemplate> {

93
	static readonly id = 'CallRenderer';
J
Johannes Rieken 已提交
94 95 96

	templateId: string = CallRenderer.id;

97
	renderTemplate(container: HTMLElement): CallRenderingTemplate {
98 99 100 101 102
		dom.addClass(container, 'callhierarchy-element');
		let icon = document.createElement('div');
		container.appendChild(icon);
		const label = new IconLabel(container, { supportHighlights: true });
		return new CallRenderingTemplate(icon, label);
J
Johannes Rieken 已提交
103
	}
J
Johannes Rieken 已提交
104

J
Johannes Rieken 已提交
105 106
	renderElement(node: ITreeNode<Call, FuzzyScore>, _index: number, template: CallRenderingTemplate): void {
		const { element, filterData } = node;
107 108
		template.icon.className = SymbolKinds.toCssClassName(element.item.kind, true);
		template.label.setLabel(
J
Johannes Rieken 已提交
109
			element.item.name,
J
Johannes Rieken 已提交
110
			element.item.detail,
111
			{ labelEscapeNewLines: true, matches: createMatches(filterData) }
J
Johannes Rieken 已提交
112 113 114
		);
	}
	disposeTemplate(template: CallRenderingTemplate): void {
115
		template.label.dispose();
J
Johannes Rieken 已提交
116 117 118 119 120 121 122 123 124 125 126 127 128
	}
}

export class VirtualDelegate implements IListVirtualDelegate<Call> {

	getHeight(_element: Call): number {
		return 22;
	}

	getTemplateId(_element: Call): string {
		return CallRenderer.id;
	}
}