From bff041f997a6de0cbba9df243c1b7dc3a6f84006 Mon Sep 17 00:00:00 2001 From: Shi Chen Date: Mon, 18 Apr 2022 18:07:12 +0800 Subject: [PATCH] adopt new reference-view API Signed-off-by: Shi Chen --- package.json | 65 ++++++++++++++++++-- package.nls.json | 5 +- package.nls.zh.json | 5 +- src/commands.ts | 14 ++++- src/standardLanguageClient.ts | 71 ++++++++++++++++++---- src/typeHierarchy/model.ts | 2 +- src/typeHierarchy/protocol.ts | 4 ++ src/typeHierarchy/references-view.d.ts | 7 +++ src/typeHierarchy/typeHierarchyTree.ts | 31 +++++++--- src/typeHierarchy/util.ts | 2 +- test/standard-mode-suite/extension.test.ts | 4 +- 11 files changed, 176 insertions(+), 34 deletions(-) diff --git a/package.json b/package.json index af3f7ea1d9..8656139f1e 100644 --- a/package.json +++ b/package.json @@ -965,8 +965,21 @@ "category": "Java" }, { - "command": "java.action.changeBaseType", - "title": "%java.action.changeBaseType%", + "command": "java.action.showClassHierarchyFromReferenceView", + "title": "%java.action.showClassHierarchy%", + "icon": "$(type-hierarchy)", + "category": "Java" + }, + { + "command": "java.action.showSupertypeHierarchy", + "title": "%java.action.showSupertypeHierarchy%", + "icon": "$(type-hierarchy-super)", + "category": "Java" + }, + { + "command": "java.action.showSubtypeHierarchy", + "title": "%java.action.showSubtypeHierarchy%", + "icon": "$(type-hierarchy-sub)", "category": "Java" } ], @@ -1050,10 +1063,18 @@ }, { "command": "java.action.showClassHierarchy", - "when": "javaLSReady && editorIsOpen" + "when": "javaLSReady && editorIsOpen && reference-list.source != typeHierarchy" }, { - "command": "java.action.changeBaseType", + "command": "java.action.showClassHierarchyFromReferenceView", + "when": "javaLSReady && editorIsOpen && reference-list.source == typeHierarchy" + }, + { + "command": "java.action.showSubtypeHierarchy", + "when": "false" + }, + { + "command": "java.action.showSupertypeHierarchy", "when": "false" }, { @@ -1077,11 +1098,43 @@ "when": "java:serverMode == LightWeight" } ], + "view/title": [ + { + "command": "java.action.showClassHierarchyFromReferenceView", + "group": "navigation@-1", + "when": "view == references-view.tree && reference-list.hasResult && reference-list.source == typeHierarchy" + }, + { + "command": "java.action.showSupertypeHierarchy", + "group": "navigation@0", + "when": "view == references-view.tree && reference-list.hasResult && reference-list.source == javaTypeHierarchy" + }, + { + "command": "java.action.showSubtypeHierarchy", + "group": "navigation@1", + "when": "view == references-view.tree && reference-list.hasResult && reference-list.source == javaTypeHierarchy" + } + ], "view/item/context": [ { - "command": "java.action.changeBaseType", + "command": "java.action.showClassHierarchy", + "group": "1", + "when": "view == references-view.tree && viewItem == java-type-item" + }, + { + "command": "java.action.showClassHierarchyFromReferenceView", + "group": "1", + "when": "view == references-view.tree && viewItem == type-item" + }, + { + "command": "java.action.showSupertypeHierarchy", + "group": "1", + "when": "view == references-view.tree && viewItem == java-type-item" + }, + { + "command": "java.action.showSubtypeHierarchy", "group": "1", - "when": "view == references-view.tree && reference-list.hasResult && reference-list.source == javaTypeHierarchy && viewItem != 'false'" + "when": "view == references-view.tree && viewItem == java-type-item" } ] } diff --git a/package.nls.json b/package.nls.json index b9c2b17446..d2a98837fa 100644 --- a/package.nls.json +++ b/package.nls.json @@ -15,5 +15,6 @@ "java.show.server.task.status": "Show Build Job Status", "java.action.navigateToSuperImplementation": "Go to Super Implementation", "java.action.showClassHierarchy": "Show Class Hierarchy", - "java.action.changeBaseType": "Base on this Type" -} \ No newline at end of file + "java.action.showSupertypeHierarchy": "Show Supertype Hierarchy", + "java.action.showSubtypeHierarchy": "Show Subtype Hierarchy" +} diff --git a/package.nls.zh.json b/package.nls.zh.json index f8d8e3f003..a335a56c0f 100644 --- a/package.nls.zh.json +++ b/package.nls.zh.json @@ -15,5 +15,6 @@ "java.show.server.task.status": "显示工作状态", "java.action.navigateToSuperImplementation": "转到父类实现", "java.action.showClassHierarchy": "显示类的继承关系", - "java.action.changeBaseType": "基于此类型" -} \ No newline at end of file + "java.action.showSupertypeHierarchy": "显示父类层次结构", + "java.action.showSubtypeHierarchy": "显示子类层次结构" +} diff --git a/src/commands.ts b/src/commands.ts index cf6dd2f188..577785eeb1 100644 --- a/src/commands.ts +++ b/src/commands.ts @@ -193,13 +193,21 @@ export namespace Commands { */ export const NAVIGATE_TO_SUPER_IMPLEMENTATION_COMMAND = 'java.action.navigateToSuperImplementation'; /** - * Show Class Hierarchy of given Selection. + * Show Supertype Hierarchy of given type. + */ + export const SHOW_SUPERTYPE_HIERARCHY = 'java.action.showSupertypeHierarchy'; + /** + * Show Subtype Hierarchy of given type. + */ + export const SHOW_SUBTYPE_HIERARCHY = 'java.action.showSubtypeHierarchy'; + /** + * Show Class Hierarchy of given type. */ export const SHOW_CLASS_HIERARCHY = 'java.action.showClassHierarchy'; /** - * Change the base type of Type Hierarchy. + * Show Class Hierarchy of given type from reference view. */ - export const CHANGE_BASE_TYPE = 'java.action.changeBaseType'; + export const SHOW_CLASS_HIERARCHY_FROM_REFERENCE_VIEW = 'java.action.showClassHierarchyFromReferenceView'; /** * Show server task status */ diff --git a/src/standardLanguageClient.ts b/src/standardLanguageClient.ts index a522b89a0d..9406f6d6eb 100644 --- a/src/standardLanguageClient.ts +++ b/src/standardLanguageClient.ts @@ -1,6 +1,6 @@ 'use strict'; -import { ExtensionContext, window, workspace, commands, Uri, ProgressLocation, ViewColumn, EventEmitter, extensions, Location, languages, CodeActionKind, TextEditor, CancellationToken, ConfigurationTarget, Range, Position } from "vscode"; +import { ExtensionContext, window, workspace, commands, Uri, ProgressLocation, ViewColumn, EventEmitter, extensions, Location, languages, CodeActionKind, TextEditor, CancellationToken, ConfigurationTarget, Range, Position, TypeHierarchyItem } from "vscode"; import { Commands } from "./commands"; import { serverStatus, ServerStatusKind } from "./serverStatus"; import { prepareExecutable, awaitServerConnection } from "./javaServerStarter"; @@ -35,7 +35,7 @@ import { findRuntimes, IJavaRuntime } from "jdk-utils"; import { snippetCompletionProvider } from "./snippetCompletionProvider"; import { JavaInlayHintsProvider } from "./inlayHintsProvider"; import { TypeHierarchyFeature } from "vscode-languageclient/lib/common/proposed.typeHierarchy"; -import { CodeTypeHierarchyItem } from "./typeHierarchy/protocol"; +import { CodeTypeHierarchyItem, showSubtypeHierarchyReferenceViewCommand, showSupertypeHierarchyReferenceViewCommand, showTypeHierarchyReferenceViewCommand } from "./typeHierarchy/protocol"; const extensionName = 'Language Support for Java'; const GRADLE_CHECKSUM = "gradle/checksum/prompt"; @@ -376,19 +376,68 @@ export class StandardLanguageClient { } })); - context.subscriptions.push(commands.registerCommand(Commands.SHOW_CLASS_HIERARCHY, (location: any) => { - if (location instanceof Uri) { - typeHierarchyTree.setTypeHierarchy(new Location(location, window.activeTextEditor.selection.active)); - } else { - if (window.activeTextEditor?.document?.languageId !== "java") { - return; + context.subscriptions.push(commands.registerCommand(Commands.SHOW_CLASS_HIERARCHY, async (anchor: any) => { + try { + if (anchor instanceof Uri) { // comes from context menu + await typeHierarchyTree.setTypeHierarchy(new Location(anchor, window.activeTextEditor.selection.active)); + } else if (anchor instanceof TypeHierarchyItem) { // comes from class hierarchy view item + await typeHierarchyTree.setTypeHierarchy(new Location(anchor.uri, anchor.range.start)); + } else { // comes from command palette + if (window.activeTextEditor?.document?.languageId !== "java") { + return; + } + await typeHierarchyTree.setTypeHierarchy(new Location(window.activeTextEditor.document.uri, window.activeTextEditor.selection.active)); + } + } catch (e) { + if (e?.message) { + // show message in the selection when call from editor context menu + if (anchor instanceof Uri) { + showNoLocationFound(e.message); + } else { + window.showErrorMessage(e.message); + } } - typeHierarchyTree.setTypeHierarchy(new Location(window.activeTextEditor.document.uri, window.activeTextEditor.selection.active)); } })); - context.subscriptions.push(commands.registerCommand(Commands.CHANGE_BASE_TYPE, async (item: CodeTypeHierarchyItem) => { - typeHierarchyTree.changeBaseItem(item); + context.subscriptions.push(commands.registerCommand(Commands.SHOW_CLASS_HIERARCHY_FROM_REFERENCE_VIEW, async (anchor?: any) => { + try { + if (!anchor) { // comes from reference-view's title or command palette + await typeHierarchyTree.setTypeHierarchyFromReferenceView(); + } else if (anchor.item instanceof TypeHierarchyItem) { // comes from reference-view's item + await typeHierarchyTree.setTypeHierarchy(new Location(anchor.item.uri, anchor.item.range.start)); + } + } catch (e) { + if (e?.message) { + window.showErrorMessage(e.message); + } + } + })); + + context.subscriptions.push(commands.registerCommand(Commands.SHOW_SUPERTYPE_HIERARCHY, async (anchor?: any) => { + let location: Location; + if (!anchor) { + location = typeHierarchyTree.getAnchor(); + } else if (anchor instanceof TypeHierarchyItem) { + location = new Location(anchor.uri, anchor.range.start); + } + if (location) { + await commands.executeCommand(showTypeHierarchyReferenceViewCommand); + await commands.executeCommand(showSupertypeHierarchyReferenceViewCommand, location); + } + })); + + context.subscriptions.push(commands.registerCommand(Commands.SHOW_SUBTYPE_HIERARCHY, async (anchor?: any) => { + let location: Location; + if (!anchor) { + location = typeHierarchyTree.getAnchor(); + } else if (anchor instanceof TypeHierarchyItem) { + location = new Location(anchor.uri, anchor.range.start); + } + if (location) { + await commands.executeCommand(showTypeHierarchyReferenceViewCommand); + await commands.executeCommand(showSubtypeHierarchyReferenceViewCommand, location); + } })); context.subscriptions.push(commands.registerCommand(Commands.COMPILE_WORKSPACE, (isFullCompile: boolean, token?: CancellationToken) => { diff --git a/src/typeHierarchy/model.ts b/src/typeHierarchy/model.ts index b498eea0a8..fa37d2302c 100644 --- a/src/typeHierarchy/model.ts +++ b/src/typeHierarchy/model.ts @@ -92,7 +92,7 @@ class TypeHierarchyTreeDataProvider implements vscode.TreeDataProvider): void; + + /** + * Get the contents of the references viewlet. + * + * @returns The current symbol tree input object + */ + getInput(): SymbolTreeInput | undefined; } /** diff --git a/src/typeHierarchy/typeHierarchyTree.ts b/src/typeHierarchy/typeHierarchyTree.ts index c39e0dcafb..5de246b7ba 100644 --- a/src/typeHierarchy/typeHierarchyTree.ts +++ b/src/typeHierarchy/typeHierarchyTree.ts @@ -5,13 +5,14 @@ import { getActiveLanguageClient } from "../extension"; import { showNoLocationFound } from "../standardLanguageClient"; import { TypeHierarchyTreeInput } from "./model"; import { CodeTypeHierarchyItem } from "./protocol"; -import { SymbolTree } from "./references-view"; +import { SymbolTree, SymbolTreeInput } from "./references-view"; import { ToCodeTypeHierarchyItem } from "./util"; export class TypeHierarchyTree { private api: SymbolTree; private client: LanguageClient; private cancelTokenSource: vscode.CancellationTokenSource; + private anchor: vscode.Location; public initialized: boolean; constructor() { @@ -52,22 +53,38 @@ export class TypeHierarchyTree { return; } if (!protocolItems || protocolItems.length === 0) { - showNoLocationFound('No Class Hierarchy found'); - return; + throw new Error("No Class Hierarchy found"); } const protocolItem = protocolItems[0]; const symbolKind = this.client.protocol2CodeConverter.asSymbolKind(protocolItem.kind); if (symbolKind === vscode.SymbolKind.Interface) { - showNoLocationFound('Class Hierarchy is not available for interfaces'); - return; + throw new Error("Class Hierarchy is not available for interfaces"); } const item: CodeTypeHierarchyItem = ToCodeTypeHierarchyItem(this.client, protocolItem); const input: TypeHierarchyTreeInput = new TypeHierarchyTreeInput(location, this.cancelTokenSource.token, item); + this.anchor = input.location; this.api.setInput(input); } - public async changeBaseItem(item: CodeTypeHierarchyItem): Promise { - this.setTypeHierarchy(new vscode.Location(item.uri, item.range.start)); + public async setTypeHierarchyFromReferenceView(): Promise { + if (!this.initialized) { + await this.initialize(); + } + if (!this.api) { + return; + } + const treeInput: SymbolTreeInput = this.api.getInput(); + if (!treeInput) { + return; + } + const location = treeInput.location; + if (location) { + await this.setTypeHierarchy(location); + } + } + + public getAnchor(): vscode.Location | undefined { + return this.anchor; } private async isValidRequestPosition(uri: vscode.Uri, position: vscode.Position) { diff --git a/src/typeHierarchy/util.ts b/src/typeHierarchy/util.ts index f163701aba..02b9d25222 100644 --- a/src/typeHierarchy/util.ts +++ b/src/typeHierarchy/util.ts @@ -1,4 +1,4 @@ -import { CancellationToken, commands, SymbolKind } from "vscode"; +import { CancellationToken, SymbolKind } from "vscode"; import { LanguageClient, Proposed, TypeHierarchyItem } from "vscode-languageclient/node"; import { CodeTypeHierarchyItem } from "./protocol"; diff --git a/test/standard-mode-suite/extension.test.ts b/test/standard-mode-suite/extension.test.ts index 77de5ff05c..58c9cef127 100644 --- a/test/standard-mode-suite/extension.test.ts +++ b/test/standard-mode-suite/extension.test.ts @@ -66,8 +66,10 @@ suite('Java Language Extension - Standard', () => { Commands.SWITCH_SERVER_MODE, Commands.UPDATE_SOURCE_ATTACHMENT_CMD, Commands.RUNTIME_VALIDATION_OPEN, - Commands.CHANGE_BASE_TYPE, Commands.SHOW_CLASS_HIERARCHY, + Commands.SHOW_CLASS_HIERARCHY_FROM_REFERENCE_VIEW, + Commands.SHOW_SUPERTYPE_HIERARCHY, + Commands.SHOW_SUBTYPE_HIERARCHY, ].sort(); const foundJavaCommands = commands.filter((value) => { return JAVA_COMMANDS.indexOf(value)>=0 || value.startsWith('java.');