deploy: current vibn theia state
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

Made-with: Cursor
This commit is contained in:
2026-02-27 12:01:08 -08:00
commit 8bb5110148
3782 changed files with 640947 additions and 0 deletions

View File

@@ -0,0 +1,10 @@
/** @type {import('eslint').Linter.Config} */
module.exports = {
extends: [
'../../configs/build.eslintrc.json'
],
parserOptions: {
tsconfigRootDir: __dirname,
project: 'tsconfig.json'
}
};

View File

@@ -0,0 +1,31 @@
<div align='center'>
<br />
<img src='https://raw.githubusercontent.com/eclipse-theia/theia/master/logo/theia.svg?sanitize=true' alt='theia-ext-logo' width='100px' />
<h2>ECLIPSE THEIA - TYPEHIERARCHY EXTENSION</h2>
<hr />
</div>
## Description
The `@theia/typehierarchy` extension includes support for `super` and `subtype` information for document symbols.
## Additional Information
- [API documentation for `@theia/typehierarchy`](https://eclipse-theia.github.io/theia/docs/next/modules/_theia_typehierarchy.html)
- [Theia - GitHub](https://github.com/eclipse-theia/theia)
- [Theia - Website](https://theia-ide.org/)
## License
- [Eclipse Public License 2.0](http://www.eclipse.org/legal/epl-2.0/)
- [一 (Secondary) GNU General Public License, version 2 with the GNU Classpath Exception](https://projects.eclipse.org/license/secondary-gpl-2.0-cp)
## Trademark
"Theia" is a trademark of the Eclipse Foundation
<https://www.eclipse.org/theia>

View File

@@ -0,0 +1,49 @@
{
"name": "@theia/typehierarchy",
"version": "1.68.0",
"description": "Theia - Type Hierarchy Extension",
"dependencies": {
"@theia/core": "1.68.0",
"@theia/editor": "1.68.0",
"tslib": "^2.6.2"
},
"publishConfig": {
"access": "public"
},
"theiaExtensions": [
{
"frontend": "lib/browser/typehierarchy-frontend-module"
}
],
"keywords": [
"theia-extension"
],
"license": "EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0",
"repository": {
"type": "git",
"url": "https://github.com/eclipse-theia/theia.git"
},
"bugs": {
"url": "https://github.com/eclipse-theia/theia/issues"
},
"homepage": "https://github.com/eclipse-theia/theia",
"files": [
"lib",
"src"
],
"scripts": {
"build": "theiaext build",
"clean": "theiaext clean",
"compile": "theiaext compile",
"lint": "theiaext lint",
"test": "theiaext test",
"watch": "theiaext watch"
},
"devDependencies": {
"@theia/ext-scripts": "1.68.0"
},
"nyc": {
"extends": "../../configs/nyc.json"
},
"gitHead": "21358137e41342742707f660b8e222f940a27652"
}

View File

@@ -0,0 +1,20 @@
// *****************************************************************************
// Copyright (C) 2022 Ericsson 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
// *****************************************************************************
export * from './typehierarchy';
export * from './typehierarchy-contribution';
export * from './typehierarchy-frontend-module';
export * from './typehierarchy-service';

View File

@@ -0,0 +1,28 @@
/********************************************************************************
* Copyright (C) 2019 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
********************************************************************************/
.theia-type-hierarchy-tree {
font-size: var(--theia-ui-font-size0);
}
.theia-type-hierarchy-tree .theia-caption-suffix {
padding-left: 10px !important;
}
.theia-type-hierarchy-tree .theia-caption-prefix {
padding-right: 5px !important;
padding-left: 1px !important;
}

View File

@@ -0,0 +1,35 @@
// *****************************************************************************
// Copyright (C) 2019 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 { interfaces, Container } from '@theia/core/shared/inversify';
import { createTreeContainer, } from '@theia/core/lib/browser/tree';
import { TypeHierarchyTree } from './typehierarchy-tree';
import { TypeHierarchyTreeModel } from './typehierarchy-tree-model';
import { TypeHierarchyTreeWidget } from './typehierarchy-tree-widget';
function createHierarchyTreeContainer(parent: interfaces.Container): Container {
const child = createTreeContainer(parent, {
tree: TypeHierarchyTree,
model: TypeHierarchyTreeModel,
widget: TypeHierarchyTreeWidget
});
return child;
}
export function createHierarchyTreeWidget(parent: interfaces.Container): TypeHierarchyTreeWidget {
return createHierarchyTreeContainer(parent).get(TypeHierarchyTreeWidget);
}

View File

@@ -0,0 +1,83 @@
// *****************************************************************************
// Copyright (C) 2019 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 { inject, injectable } from '@theia/core/shared/inversify';
import { TreeNode } from '@theia/core/lib/browser/tree/tree';
import { TreeModelImpl } from '@theia/core/lib/browser/tree/tree-model';
import { TypeHierarchyRegistry, TypeHierarchyDirection, TypeHierarchyParams } from '../typehierarchy-provider';
import { TypeHierarchyTree } from './typehierarchy-tree';
@injectable()
export class TypeHierarchyTreeModel extends TreeModelImpl {
@inject(TypeHierarchyRegistry)
protected readonly registry: TypeHierarchyRegistry;
protected override doOpenNode(node: TreeNode): void {
// do nothing (in particular do not expand the node)
}
/**
* Initializes the tree by calculating and setting a new tree root node.
*/
async initialize(options: TypeHierarchyTree.InitOptions): Promise<void> {
this.tree.root = undefined;
(this.tree as TypeHierarchyTree).provider = undefined;
const { location, languageId, direction } = options;
if (languageId && location) {
const provider = await this.registry.get(languageId);
if (provider) {
const params: TypeHierarchyParams = {
textDocument: {
uri: location.uri
},
position: location.range.start,
direction,
resolve: 1
};
const symbol = await provider.get(params);
if (symbol) {
const root = TypeHierarchyTree.RootNode.create(symbol, direction);
root.expanded = true;
this.tree.root = root;
(this.tree as TypeHierarchyTree).provider = provider;
}
}
}
}
/**
* If the tree root is set, it resets it with the inverse type hierarchy direction.
*/
async flipDirection(): Promise<void> {
const { root } = this.tree;
const service = (this.tree as TypeHierarchyTree).provider;
if (TypeHierarchyTree.RootNode.is(root) && !!service) {
const { direction, item } = root;
const { uri, selectionRange } = item;
const location = {
uri,
range: selectionRange
};
this.initialize({
direction: direction === TypeHierarchyDirection.Children ? TypeHierarchyDirection.Parents : TypeHierarchyDirection.Children,
location,
languageId: service.languageId
});
}
}
}

View File

@@ -0,0 +1,108 @@
// *****************************************************************************
// Copyright (C) 2019 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 * as React from '@theia/core/shared/react';
import { inject, injectable } from '@theia/core/shared/inversify';
import { DockPanel } from '@theia/core/shared/@lumino/widgets';
import URI from '@theia/core/lib/common/uri';
import { SymbolKind, Range } from '@theia/core/shared/vscode-languageserver-protocol';
import { TreeNode } from '@theia/core/lib/browser/tree/tree';
import { EditorManager } from '@theia/editor/lib/browser/editor-manager';
import { ContextMenuRenderer } from '@theia/core/lib/browser/context-menu-renderer';
import { TreeWidget, TreeProps } from '@theia/core/lib/browser/tree/tree-widget';
import { TypeHierarchyTreeModel } from './typehierarchy-tree-model';
import { TypeHierarchyTree } from './typehierarchy-tree';
import { codicon } from '@theia/core/lib/browser';
import { nls } from '@theia/core/lib/common/nls';
@injectable()
export class TypeHierarchyTreeWidget extends TreeWidget {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
protected readonly icons = new Map(Array.from(Object.keys(SymbolKind)).map(key => [(SymbolKind as any)[key], key.toLocaleLowerCase()] as [number, string]));
@inject(EditorManager) readonly editorManager: EditorManager;
constructor(
@inject(TreeProps) props: TreeProps,
@inject(TypeHierarchyTreeModel) override readonly model: TypeHierarchyTreeModel,
@inject(ContextMenuRenderer) contextMenuRenderer: ContextMenuRenderer
) {
super(props, model, contextMenuRenderer);
this.id = TypeHierarchyTreeWidget.WIDGET_ID;
this.title.label = TypeHierarchyTreeWidget.WIDGET_LABEL;
this.title.caption = TypeHierarchyTreeWidget.WIDGET_LABEL;
this.addClass(TypeHierarchyTreeWidget.Styles.TYPE_HIERARCHY_TREE_CLASS);
this.title.closable = true;
this.title.iconClass = codicon('type-hierarchy');
this.toDispose.push(this.model.onSelectionChanged(selection => {
const node = selection[0];
if (node) {
this.openEditor(node, true);
}
}));
this.toDispose.push(this.model.onOpenNode(node => this.openEditor(node)));
}
/**
* Initializes the widget with the new input.
*/
async initialize(options: TypeHierarchyTree.InitOptions): Promise<void> {
await this.model.initialize(options);
}
/**
* See: `TreeWidget#renderIcon`.
*/
protected override renderIcon(node: TreeNode): React.ReactNode {
if (TypeHierarchyTree.Node.is(node)) {
return <div className={'symbol-icon-center codicon codicon-symbol-' + this.icons.get(node.item.kind) || 'unknown'}></div>;
}
return undefined;
}
/**
* Opens up the node in the editor. On demand (`keepFocus`) it reveals the location in the editor.
*/
protected async openEditor(node: TreeNode, keepFocus: boolean = false): Promise<void> {
if (TypeHierarchyTree.Node.is(node)) {
const { selectionRange, uri } = node.item;
const editorWidget = await this.editorManager.open(new URI(uri), {
mode: keepFocus ? 'reveal' : 'activate',
selection: Range.create(selectionRange.start, selectionRange.end)
});
if (editorWidget.parent instanceof DockPanel) {
editorWidget.parent.selectWidget(editorWidget);
}
}
}
}
export namespace TypeHierarchyTreeWidget {
export const WIDGET_ID = 'theia-typehierarchy';
export const WIDGET_LABEL = nls.localizeByDefault('Type Hierarchy');
/**
* CSS styles for the `Type Hierarchy` widget.
*/
export namespace Styles {
export const TYPE_HIERARCHY_TREE_CLASS = 'theia-type-hierarchy-tree';
}
}

View File

@@ -0,0 +1,190 @@
// *****************************************************************************
// Copyright (C) 2019 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
// *****************************************************************************
/* eslint-disable @typescript-eslint/no-explicit-any */
import { injectable } from '@theia/core/shared/inversify';
import { generateUuid } from '@theia/core/lib/common/uuid';
import URI from '@theia/core/lib/common/uri';
import { Location } from '@theia/editor/lib/browser/editor';
import { TreeDecoration, DecoratedTreeNode } from '@theia/core/lib/browser/tree/tree-decorator';
import { TreeImpl, TreeNode, CompositeTreeNode, ExpandableTreeNode, SelectableTreeNode } from '@theia/core/lib/browser/tree';
import { TypeHierarchyProvider, TypeHierarchyDirection, ResolveTypeHierarchyItemParams, TypeHierarchyItem } from '../typehierarchy-provider';
@injectable()
export class TypeHierarchyTree extends TreeImpl {
provider: TypeHierarchyProvider | undefined;
override async resolveChildren(parent: CompositeTreeNode): Promise<TreeNode[]> {
if (TypeHierarchyTree.Node.is(parent)) {
await this.ensureResolved(parent);
if (parent.children.length === 0) {
delete (parent as any).children;
delete (parent as any).expanded;
return [];
}
return parent.children.slice();
}
return [];
}
/**
* Returns with the direction of the type hierarchy attached to the root node. `undefined` if the root is not set.
*/
protected get direction(): TypeHierarchyDirection | undefined {
if (TypeHierarchyTree.RootNode.is(this.root)) {
return this.root.direction;
}
return undefined;
}
/**
* Makes sure, the node and its children are resolved. Resolves it on demand.
*/
protected async ensureResolved(node: TypeHierarchyTree.Node): Promise<void> {
if (!node.resolved) {
const { provider, direction } = this;
if (provider && direction !== undefined) {
const { item } = node;
const param: ResolveTypeHierarchyItemParams = {
item,
direction,
resolve: 1
};
const resolvedItem = await provider.resolve(param);
if (resolvedItem) {
node.resolved = true;
const items = TypeHierarchyDirection.Children === direction ? resolvedItem.children : resolvedItem.parents;
if (items) {
node.children = items.map(child => TypeHierarchyTree.Node.create(child, direction, false));
} else {
node.children = [];
}
}
}
}
}
}
export namespace TypeHierarchyTree {
export interface InitOptions {
readonly direction: TypeHierarchyDirection;
readonly location: Location | undefined;
readonly languageId: string | undefined;
}
export interface RootNode extends Node {
readonly direction: TypeHierarchyDirection;
}
export namespace RootNode {
export function is(node: TreeNode | undefined): node is RootNode {
if (Node.is(node) && 'direction' in node) {
const { direction } = (node as RootNode);
return direction === TypeHierarchyDirection.Children || direction === TypeHierarchyDirection.Parents;
}
return false;
}
export function create(item: TypeHierarchyItem, direction: TypeHierarchyDirection): RootNode {
return {
...Node.create(item, direction, true),
direction
};
}
}
export interface Node extends CompositeTreeNode, ExpandableTreeNode, SelectableTreeNode, DecoratedTreeNode {
readonly item: TypeHierarchyItem;
resolved: boolean;
}
export namespace Node {
export function is(node: TreeNode | undefined): node is Node {
if (!!node && 'resolved' in node && 'item' in node) {
const { resolved, item } = (node as Node);
return typeof resolved === 'boolean' && !!item;
}
return false;
}
export function create(item: TypeHierarchyItem, direction: TypeHierarchyDirection, resolved: boolean = true): Node {
const items = TypeHierarchyDirection.Children === direction ? item.children : item.parents;
if (items && items.length > 0) {
// If the server sent more levels than requested, use them.
resolved = true;
}
const node = {
id: generateUuid(),
name: item.name,
description: item.detail,
parent: undefined,
location: Location.create(item.uri, item.selectionRange),
resolved,
children: items ? items.map(child => create(child, direction, false)) : [],
expanded: false,
visible: true,
selected: false,
kind: item.kind,
decorationData: decorationData(item, direction),
item
};
// Trick: if the node is `resolved` and have zero `children`, make the node non-expandable.
if (resolved && node.children.length === 0) {
delete (node as any).expanded;
}
return node;
}
function decorationData(item: TypeHierarchyItem, direction: TypeHierarchyDirection): TreeDecoration.Data {
const captionSuffixes: TreeDecoration.CaptionAffix[] = [{
data: new URI(item.uri).displayName,
fontData: {
color: 'var(--theia-descriptionForeground)',
}
}];
if (item.detail) {
captionSuffixes.unshift({
data: item.detail,
fontData: {
color: 'var(--theia-list-highlightForeground)',
style: 'italic'
}
});
}
const data = `${TypeHierarchyDirection.Children === direction ? '▼' : '▲'}`;
const color = `var(${TypeHierarchyDirection.Children === direction ? '--theia-errorForeground' : '--theia-successBackground'})`;
return {
captionSuffixes,
captionPrefixes: [{
data,
fontData: {
color,
style: 'bold'
}
}]
};
}
}
}

View File

@@ -0,0 +1,175 @@
// *****************************************************************************
// Copyright (C) 2019 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, inject, named, postConstruct } from '@theia/core/shared/inversify';
import { MenuModelRegistry } from '@theia/core/lib/common/menu';
import { ApplicationShell } from '@theia/core/lib/browser/shell';
import { KeybindingRegistry } from '@theia/core/lib/browser/keybinding';
import { Command, CommandRegistry } from '@theia/core/lib/common/command';
import { EDITOR_CONTEXT_MENU } from '@theia/editor/lib/browser/editor-menu';
import { EditorAccess, EditorManager } from '@theia/editor/lib/browser/editor-manager';
import { AbstractViewContribution, OpenViewArguments } from '@theia/core/lib/browser/shell/view-contribution';
import { TypeHierarchyTree } from './tree/typehierarchy-tree';
import { TypeHierarchyTreeWidget } from './tree/typehierarchy-tree-widget';
import { TypeHierarchyDirection } from './typehierarchy-provider';
import { TypeHierarchyServiceProvider } from './typehierarchy-service';
import URI from '@theia/core/lib/common/uri';
import { ContextKey, ContextKeyService } from '@theia/core/lib/browser/context-key-service';
@injectable()
export class TypeHierarchyContribution extends AbstractViewContribution<TypeHierarchyTreeWidget> {
@inject(ApplicationShell)
protected override readonly shell: ApplicationShell;
@inject(EditorAccess)
@named(EditorAccess.CURRENT)
protected readonly editorAccess: EditorAccess;
@inject(EditorManager)
protected readonly editorManager: EditorManager;
@inject(ContextKeyService) protected readonly contextKeyService: ContextKeyService;
protected editorHasTypeHierarchyProvider!: ContextKey<boolean>;
@inject(TypeHierarchyServiceProvider)
protected readonly typeHierarchyServiceProvider: TypeHierarchyServiceProvider;
constructor() {
super({
widgetId: TypeHierarchyTreeWidget.WIDGET_ID,
widgetName: TypeHierarchyTreeWidget.WIDGET_LABEL,
defaultWidgetOptions: {
area: 'bottom'
},
toggleCommandId: TypeHierarchyCommands.TOGGLE_VIEW.id,
toggleKeybinding: 'ctrlcmd+shift+h'
});
}
@postConstruct()
protected init(): void {
this.editorHasTypeHierarchyProvider = this.contextKeyService.createKey('editorHasTypeHierarchyProvider', false);
this.editorManager.onCurrentEditorChanged(() => this.editorHasTypeHierarchyProvider.set(this.isTypeHierarchyAvailable()));
this.typeHierarchyServiceProvider.onDidChange(() => this.editorHasTypeHierarchyProvider.set(this.isTypeHierarchyAvailable()));
}
protected isTypeHierarchyAvailable(): boolean {
const { selection, languageId } = this.editorAccess;
return !!selection && !!languageId && !!this.typeHierarchyServiceProvider.get(languageId, new URI(selection.uri));
}
override async openView(args?: Partial<TypeHierarchyOpenViewArguments>): Promise<TypeHierarchyTreeWidget> {
const widget = await super.openView(args);
const { selection, languageId } = this.editorAccess;
const direction = this.getDirection(args);
await widget.initialize({ location: selection, languageId, direction });
return widget;
}
override registerCommands(commands: CommandRegistry): void {
super.registerCommands(commands);
commands.registerCommand(TypeHierarchyCommands.OPEN_SUBTYPE, {
execute: () => this.openViewOrFlipHierarchyDirection(TypeHierarchyDirection.Children),
isEnabled: this.isEnabled.bind(this)
});
commands.registerCommand(TypeHierarchyCommands.OPEN_SUPERTYPE, {
execute: () => this.openViewOrFlipHierarchyDirection(TypeHierarchyDirection.Parents),
isEnabled: this.isEnabled.bind(this)
});
}
override registerMenus(menus: MenuModelRegistry): void {
super.registerMenus(menus);
const menuPath = [...EDITOR_CONTEXT_MENU, 'type-hierarchy'];
menus.registerMenuAction(menuPath, {
commandId: TypeHierarchyCommands.OPEN_SUBTYPE.id
});
menus.registerMenuAction(menuPath, {
commandId: TypeHierarchyCommands.OPEN_SUPERTYPE.id
});
}
override registerKeybindings(keybindings: KeybindingRegistry): void {
super.registerKeybindings(keybindings);
keybindings.registerKeybinding({
command: TypeHierarchyCommands.OPEN_SUBTYPE.id,
keybinding: 'ctrlcmd+alt+h'
});
}
/**
* Flips the hierarchy direction in the `Type Hierarchy` view, if it is active and has a valid root.
* Otherwise, calculates the type hierarchy based on the selection of the current editor.
*/
protected async openViewOrFlipHierarchyDirection(direction: TypeHierarchyDirection): Promise<void> {
if (this.isEnabled()) {
const { activeWidget } = this.shell;
if (activeWidget instanceof TypeHierarchyTreeWidget && TypeHierarchyTree.RootNode.is(activeWidget.model.root)) {
await activeWidget.model.flipDirection();
} else {
await this.openView({
toggle: false,
activate: true,
direction
});
}
}
}
/**
* Enabled if the `current` editor has the `languageId` or the `Type Hierarchy` widget is the active one.
*/
protected isEnabled(languageId: string | undefined = this.editorAccess.languageId): boolean {
return !!languageId || this.shell.activeWidget instanceof TypeHierarchyTreeWidget;
}
/**
* Extracts the type hierarchy direction from the argument. If the direction cannot be extracted, returns with the `Children` as the default type.
*/
protected getDirection(args?: Partial<TypeHierarchyOpenViewArguments>): TypeHierarchyDirection {
return !!args && !!args.direction ? args.direction : TypeHierarchyDirection.Children;
}
}
export interface TypeHierarchyOpenViewArguments extends OpenViewArguments {
/**
* The type hierarchy direction for the view argument.
*/
readonly direction: TypeHierarchyDirection;
}
export namespace TypeHierarchyCommands {
export const TOGGLE_VIEW: Command = {
id: 'typehierarchy:toggle'
};
export const OPEN_SUBTYPE = Command.toLocalizedCommand({
id: 'typehierarchy:open-subtype',
label: 'Subtype Hierarchy'
}, 'theia/typehierarchy/subtypeHierarchy');
export const OPEN_SUPERTYPE = Command.toLocalizedCommand({
id: 'typehierarchy:open-supertype',
label: 'Supertype Hierarchy'
}, 'theia/typehierarchy/supertypeHierarchy');
}

View File

@@ -0,0 +1,38 @@
// *****************************************************************************
// Copyright (C) 2019 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 { bindContributionProvider } from '@theia/core/lib/common';
import { ContainerModule } from '@theia/core/shared/inversify';
import { WidgetFactory } from '@theia/core/lib/browser/widget-manager';
import { bindViewContribution } from '@theia/core/lib/browser/shell/view-contribution';
import { TypeHierarchyRegistry } from './typehierarchy-provider';
import { TypeHierarchyContribution } from './typehierarchy-contribution';
import { TypeHierarchyTreeWidget } from './tree/typehierarchy-tree-widget';
import { TypeHierarchyService, TypeHierarchyServiceProvider } from './typehierarchy-service';
import { createHierarchyTreeWidget } from './tree/typehierarchy-tree-container';
import '../../src/browser/style/index.css';
export default new ContainerModule(bind => {
bindContributionProvider(bind, TypeHierarchyService);
bind(TypeHierarchyServiceProvider).to(TypeHierarchyServiceProvider).inSingletonScope();
bind(TypeHierarchyRegistry).toSelf().inSingletonScope();
bindViewContribution(bind, TypeHierarchyContribution);
bind(WidgetFactory).toDynamicValue(context => ({
id: TypeHierarchyTreeWidget.WIDGET_ID,
createWidget: () => createHierarchyTreeWidget(context.container)
}));
});

View File

@@ -0,0 +1,163 @@
// *****************************************************************************
// Copyright (C) 2019 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 { Disposable } from '@theia/core/lib/common/disposable';
import { SymbolKind, Range, TextDocumentPositionParams } from '@theia/core/shared/vscode-languageserver-protocol';
@injectable()
export class TypeHierarchyRegistry {
protected readonly providers = new Map<string, TypeHierarchyProvider>();
async get(languageId: string | undefined): Promise<TypeHierarchyProvider | undefined> {
return languageId ? this.providers.get(languageId) : undefined;
}
register(provider: TypeHierarchyProvider): Disposable {
const { languageId } = provider;
if (this.providers.has(languageId)) {
throw new Error(`type hierarchy provider for '${languageId}' language is already registered`);
}
this.providers.set(languageId, provider);
return Disposable.create(() => this.providers.delete(languageId));
}
}
export interface TypeHierarchyProvider extends Disposable {
readonly languageId: string;
get(params: TypeHierarchyParams): Promise<TypeHierarchyItem | undefined>;
resolve(params: ResolveTypeHierarchyItemParams): Promise<TypeHierarchyItem | undefined>;
}
/**
* The type hierarchy params is an extension of the `TextDocumentPositionParams` with optional properties
* which can be used to eagerly resolve the item when requesting from the server.
*/
export interface TypeHierarchyParams extends TextDocumentPositionParams {
/**
* The hierarchy levels to resolve. `0` indicates no level. When not defined, it is treated as `0`.
*/
resolve?: number;
/**
* The direction of the hierarchy levels to resolve.
*/
direction?: TypeHierarchyDirection
}
export const enum TypeHierarchyDirection {
/**
* Flag for retrieving/resolving the subtypes.
*/
Children,
/**
* Flag to use when retrieving/resolving the supertypes.
*/
Parents,
/**
* Flag for resolving both the super- and subtypes.
*/
Both
}
/**
* Parameters for the `typeHierarchy/resolve` request.
*/
export interface ResolveTypeHierarchyItemParams {
/**
* The item to resolve.
*/
item: TypeHierarchyItem;
/**
* The hierarchy levels to resolve. `0` indicates no level.
*/
resolve: number;
/**
* The direction of the hierarchy levels to resolve.
*/
direction: TypeHierarchyDirection;
}
export interface TypeHierarchyItem {
/**
* The human readable name of the hierarchy item.
*/
name: string;
/**
* Optional detail for the hierarchy item. It can be, for instance, the signature of a function or method.
*/
detail?: string;
/**
* The kind of the hierarchy item. For instance, class or interface.
*/
kind: SymbolKind;
/**
* `true` if the hierarchy item is deprecated. Otherwise, `false`. It is `false` by default.
*/
deprecated?: boolean;
/**
* The URI of the text document where this type hierarchy item belongs to.
*/
uri: string;
/**
* The range enclosing this type hierarchy item not including leading/trailing whitespace but everything else
* like comments. This information is typically used to determine if the clients cursor is inside the type
* hierarchy item to reveal in the symbol in the UI.
*/
range: Range;
/**
* The range that should be selected and revealed when this type hierarchy item is being picked, e.g the name
* of a function. Must be contained by the `range`.
*/
selectionRange: Range;
/**
* If this type hierarchy item is resolved, it contains the direct parents. Could be empty if the item does
* not have any direct parents. If not defined, the parents have not been resolved yet.
*/
parents?: TypeHierarchyItem[];
/**
* If this type hierarchy item is resolved, it contains the direct children of the current item. Could be
* empty if the item does not have any descendants. If not defined, the children have not been resolved.
*/
children?: TypeHierarchyItem[];
/**
* An optional data field can be used to identify a type hierarchy item in a resolve request.
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
data?: any;
}

View File

@@ -0,0 +1,89 @@
// *****************************************************************************
// Copyright (C) 2022 Ericsson 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 { CancellationToken } from '@theia/core';
import { ContributionProvider, Disposable, Emitter, Event } from '@theia/core/lib/common';
import URI from '@theia/core/lib/common/uri';
import { inject, injectable, named, postConstruct } from '@theia/core/shared/inversify';
import { DocumentUri, Position } from '@theia/core/shared/vscode-languageserver-protocol';
import { LanguageSelector, score } from '@theia/editor/lib/common/language-selector';
import { TypeHierarchyItem } from './typehierarchy';
export const TypeHierarchyService = Symbol('TypeHierarchyService');
export interface TypeHierarchySession {
items: TypeHierarchyItem[];
dispose(): void;
}
export interface TypeHierarchyService {
readonly selector: LanguageSelector;
prepareSession(uri: DocumentUri, position: Position, cancellationToken: CancellationToken): Promise<TypeHierarchySession | undefined>
provideSuperTypes(sessionId: string, itemId: string, cancellationToken: CancellationToken): Promise<TypeHierarchyItem[] | undefined>
provideSubTypes(sessionId: string, itemId: string, cancellationToken: CancellationToken): Promise<TypeHierarchyItem[] | undefined>
}
@injectable()
export class TypeHierarchyServiceProvider {
@inject(ContributionProvider) @named(TypeHierarchyService)
protected readonly contributions: ContributionProvider<TypeHierarchyService>;
protected readonly onDidChangeEmitter = new Emitter<void>();
get onDidChange(): Event<void> {
return this.onDidChangeEmitter.event;
}
private services: TypeHierarchyService[] = [];
@postConstruct()
init(): void {
this.services = this.services.concat(this.contributions.getContributions());
}
get(languageId: string, uri: URI): TypeHierarchyService | undefined {
return this.services
.filter(service => this.score(service, languageId, uri) > 0)
.sort((left, right) => this.score(right, languageId, uri) - this.score(left, languageId, uri))[0];
}
protected score(service: TypeHierarchyService, languageId: string, uri: URI): number {
return score(service.selector, uri.scheme, uri.path.toString(), languageId, true);
}
add(service: TypeHierarchyService): Disposable {
this.services.push(service);
const that = this;
this.onDidChangeEmitter.fire();
return {
dispose: () => {
that.remove(service);
}
};
}
private remove(service: TypeHierarchyService): boolean {
const length = this.services.length;
this.services = this.services.filter(value => value !== service);
const serviceWasRemoved = length !== this.services.length;
if (serviceWasRemoved) {
this.onDidChangeEmitter.fire();
}
return serviceWasRemoved;
}
}

View File

@@ -0,0 +1,31 @@
// *****************************************************************************
// Copyright (C) 2022 Ericsson 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 { UriComponents } from '@theia/core/lib/common/uri';
import { Range, SymbolKind, SymbolTag } from '@theia/core/shared/vscode-languageserver-protocol';
export interface TypeHierarchyItem {
_sessionId?: string;
_itemId?: string;
kind: SymbolKind;
tags?: readonly SymbolTag[];
name: string;
detail?: string;
uri: UriComponents;
range: Range;
selectionRange: Range;
}

View File

@@ -0,0 +1,29 @@
// *****************************************************************************
// Copyright (C) 2019 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
// *****************************************************************************
/* note: this bogus test file is required so that
we are able to run mocha unit tests on this
package, without having any actual unit tests in it.
This way a coverage report will be generated,
showing 0% coverage, instead of no report.
This file can be removed once we have real unit
tests in place. */
describe('typehierarchy package', () => {
it('support code coverage statistics', () => true);
});

View File

@@ -0,0 +1,19 @@
{
"extends": "../../configs/base.tsconfig.json",
"compilerOptions": {
"composite": true,
"rootDir": "src",
"outDir": "lib"
},
"include": [
"src"
],
"references": [
{
"path": "../core"
},
{
"path": "../editor"
}
]
}