Files
theia-code-os/packages/callhierarchy/src/browser/callhierarchy-tree/callhierarchy-tree.ts
mawkone 8bb5110148
Some checks failed
Playwright Tests / Playwright Tests (ubuntu-22.04, Node.js 22.x) (push) Has been cancelled
3PP License Check / 3PP License Check (11, 22.x, ubuntu-22.04) (push) Has been cancelled
Publish packages to NPM / Perform Publishing (push) Has been cancelled
deploy: current vibn theia state
Made-with: Cursor
2026-02-27 12:01:08 -08:00

120 lines
4.4 KiB
TypeScript

// *****************************************************************************
// Copyright (C) 2018 TypeFox and others.
//
// This program and the accompanying materials are made available under the
// terms of the Eclipse Public License v. 2.0 which is available at
// http://www.eclipse.org/legal/epl-2.0.
//
// This Source Code may also be made available under the following Secondary
// Licenses when the conditions for such availability set forth in the Eclipse
// Public License v. 2.0 are satisfied: GNU General Public License, version 2
// with the GNU Classpath Exception which is available at
// https://www.gnu.org/software/classpath/license.html.
//
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
// *****************************************************************************
import { injectable } from '@theia/core/shared/inversify';
import { TreeNode, CompositeTreeNode, SelectableTreeNode, ExpandableTreeNode, TreeImpl } from '@theia/core/lib/browser';
import { CallHierarchyItem, CallHierarchyIncomingCall } from '../callhierarchy';
import { CallHierarchyService } from '../callhierarchy-service';
import { Md5 } from 'ts-md5';
import { CancellationTokenSource } from '@theia/core/lib/common/cancellation';
@injectable()
export class CallHierarchyTree extends TreeImpl {
protected _callHierarchyService: CallHierarchyService | undefined;
set callHierarchyService(callHierarchyService: CallHierarchyService | undefined) {
this._callHierarchyService = callHierarchyService;
}
get callHierarchyService(): CallHierarchyService | undefined {
return this._callHierarchyService;
}
override async resolveChildren(parent: CompositeTreeNode): Promise<TreeNode[]> {
if (!this.callHierarchyService) {
return Promise.resolve([]);
}
if (parent.children.length > 0) {
return Promise.resolve([...parent.children]);
}
let definition: CallHierarchyItem | undefined;
if (ItemNode.is(parent)) {
definition = parent.definition;
} else if (CallerNode.is(parent)) {
definition = parent.caller.from;
}
if (definition) {
const cancellationSource = new CancellationTokenSource();
const callers = await this.callHierarchyService.getCallers(definition, cancellationSource.token);
if (!callers) {
return Promise.resolve([]);
}
return this.toNodes(callers, parent);
}
return Promise.resolve([]);
}
protected toNodes(callers: CallHierarchyIncomingCall[], parent: CompositeTreeNode): TreeNode[] {
return callers.map(caller => this.toNode(caller, parent));
}
protected toNode(caller: CallHierarchyIncomingCall, parent: CompositeTreeNode | undefined): TreeNode {
return CallerNode.create(caller, parent as TreeNode);
}
}
export interface ItemNode extends SelectableTreeNode, ExpandableTreeNode {
definition: CallHierarchyItem;
}
export namespace ItemNode {
export function is(node: TreeNode | undefined): node is ItemNode {
return !!node && 'definition' in node;
}
export function create(definition: CallHierarchyItem, parent: TreeNode | undefined): ItemNode {
const name = definition.name;
const id = createId(definition, parent);
return <ItemNode>{
id, definition, name, parent,
visible: true,
children: [],
expanded: false,
selected: false,
};
}
}
export interface CallerNode extends SelectableTreeNode, ExpandableTreeNode {
caller: CallHierarchyIncomingCall;
}
export namespace CallerNode {
export function is(node: TreeNode | undefined): node is CallerNode {
return !!node && 'caller' in node;
}
export function create(caller: CallHierarchyIncomingCall, parent: TreeNode | undefined): CallerNode {
const callerDefinition = caller.from;
const name = callerDefinition.name;
const id = createId(callerDefinition, parent);
return <CallerNode>{
id, caller, name, parent,
visible: true,
children: [],
expanded: false,
selected: false,
};
}
}
function createId(definition: CallHierarchyItem, parent: TreeNode | undefined): string {
const idPrefix = (parent) ? parent.id + '/' : '';
const id = idPrefix + Md5.hashStr(JSON.stringify(definition));
return id;
}