Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -1727,7 +1727,11 @@
},
{
"command": "java.change.searchScope",
"title": "%java.change.searchScope%",
"title": "%java.change.searchScope%"
},
{
"command": "java.action.showExtendedOutline",
"title": "%java.action.showExtendedOutline%",
"category": "Java"
}
],
Expand Down Expand Up @@ -1757,6 +1761,11 @@
"command": "java.action.doCleanup",
"key": "ctrl+shift+alt+s",
"when": "javaLSReady && editorLangId == java"
},
{
"command": "java.action.showExtendedOutline",
"key": "ctrl+o",
"when": "javaLSReady && inQuickOpen"
}
],
"menus": {
Expand Down
3 changes: 2 additions & 1 deletion package.nls.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,6 @@
"java.edit.smartSemicolonDetection": "Java Smart Semicolon Detection",
"java.action.filesExplorerPasteAction": "Paste Clipboard Text Into a File",
"java.action.doCleanup": "Performs Cleanup Actions",
"java.change.searchScope": "Change Search Scope"
"java.change.searchScope": "Change Search Scope",
"java.action.showExtendedOutline": "Open Extended Outline"
}
5 changes: 5 additions & 0 deletions src/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,11 @@ export namespace Commands {
*/
export const CHANGE_JAVA_SEARCH_SCOPE = "java.change.searchScope";

/**
* Show Extended Outline for current document.
*/
export const SHOW_EXTEND_OUTLINE = 'java.action.showExtendedOutline';

}

/**
Expand Down
81 changes: 81 additions & 0 deletions src/outline/extendedOutlineQuickPick.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import { DocumentSymbolParams, LanguageClient, TextDocumentIdentifier } from "vscode-languageclient/node";
import { getActiveLanguageClient } from "../extension";
import { ExtendedDocumentSymbolRequest } from "./protocol";
import { Location, Position, QuickPick, QuickPickItem, Uri, window, workspace } from "vscode";
import { getLThemeIcon } from "../themeUtils";

export class ExtendedOutlineQuickPick {
private api: QuickPick<QuickPickItem>;
private client: LanguageClient;
public initialized: boolean;

constructor() {
this.initialized = false;
}

async initialize() {
this.api = window.createQuickPick();
this.api.ignoreFocusOut = true;
this.api.onDidChangeActive((items: QuickPickItem[]) => {
if (items.length > 0) {
const active: QuickPickItem = items[0];
const uri = active["uri"];
const range = active["range"];
if (uri !== undefined) {
workspace.openTextDocument(Uri.parse(uri)).then(doc => {
window.showTextDocument(doc, {preserveFocus: true, selection: range});
});
} else {
window.showTextDocument(window.activeTextEditor.document, {preserveFocus: true, selection: range});
}
}
});
this.api.onDidAccept(() => {
this.api.hide();
});
this.client = await getActiveLanguageClient();
this.initialized = true;
}

async open(uri: Uri) {
if (!this.initialized) {
await this.initialize();
}

if (!this.api) {
return;
}

const location = new Location(uri, new Position(0, 0));
const params: DocumentSymbolParams = {
textDocument: TextDocumentIdentifier.create(location.uri.toString())
};
const symbols = await this.client.sendRequest(ExtendedDocumentSymbolRequest.type, params);
let quickPickItems: QuickPickItem[] = [];
for (const s of symbols) {
const icon = getLThemeIcon(s.kind).id;
const item = {
label: `$(${icon}) ${s.name}`,
description: s.detail.trim(),
uri: s.uri,
range: s.range
};
quickPickItems.push(item);
if (icon === 'symbol-class') {
const items: QuickPickItem[] = s.children.map(s => ({
label: `$(${getLThemeIcon(s.kind).id}) ${s.name}`,
// custom quick pick has automatic space between label & description
description: s.detail.trim(),
uri: s.uri,
range: s.range
}));
quickPickItems = quickPickItems.concat(items);
}
}
this.api.items = quickPickItems;
this.api.activeItems = [];
this.api.show();
}
}

export const extendedOutlineQuickPick: ExtendedOutlineQuickPick = new ExtendedOutlineQuickPick();
10 changes: 10 additions & 0 deletions src/outline/protocol.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { DocumentSymbol, DocumentSymbolParams, RequestType } from "vscode-languageclient";

export namespace ExtendedDocumentSymbolRequest {
export const type = new RequestType<DocumentSymbolParams, ExtendedDocumentSymbol[], void>('java/extendedDocumentSymbol');
}

export interface ExtendedDocumentSymbol extends DocumentSymbol {
uri: string;
children?: ExtendedDocumentSymbol[];
}
14 changes: 13 additions & 1 deletion src/standardLanguageClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ import { registerDocumentValidationListener } from './diagnostic';
import { listJdks, sortJdksBySource, sortJdksByVersion } from './jdkUtils';
import { ClientCodeActionProvider } from './clientCodeActionProvider';
import { BuildFileSelector } from './buildFilesSelector';
import { extendedOutlineQuickPick } from "./outline/extendedOutlineQuickPick";

const extensionName = 'Language Support for Java';
const GRADLE_CHECKSUM = "gradle/checksum/prompt";
Expand Down Expand Up @@ -593,6 +594,17 @@ export class StandardLanguageClient {
}
}));

context.subscriptions.push(commands.registerCommand(Commands.SHOW_EXTEND_OUTLINE, (location: any) => {
if (location instanceof Uri) {
extendedOutlineQuickPick.open(location);
} else {
if (window.activeTextEditor?.document?.languageId !== "java") {
return;
}
extendedOutlineQuickPick.open(window.activeTextEditor.document.uri);
}
}));

buildPath.registerCommands(context);
sourceAction.registerCommands(this.languageClient, context);
refactorAction.registerCommands(this.languageClient, context);
Expand Down Expand Up @@ -897,4 +909,4 @@ export class DisableWillRenameFeature implements StaticFeature {
fillInitializeParams?: () => void;
preInitialize?: () => void;
initialize(): void {}
}
}
20 changes: 20 additions & 0 deletions src/themeUtils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { SymbolKind as VSymbolKind, ThemeIcon } from "vscode";
import { SymbolKind as LSymbolKind} from "vscode-languageclient";

const themeIconIds = [
'symbol-file', 'symbol-module', 'symbol-namespace', 'symbol-package', 'symbol-class', 'symbol-method',
'symbol-property', 'symbol-field', 'symbol-constructor', 'symbol-enum', 'symbol-interface',
'symbol-function', 'symbol-variable', 'symbol-constant', 'symbol-string', 'symbol-number', 'symbol-boolean',
'symbol-array', 'symbol-object', 'symbol-key', 'symbol-null', 'symbol-enum-member', 'symbol-struct',
'symbol-event', 'symbol-operator', 'symbol-type-parameter'
];

export function getLThemeIcon(kind: LSymbolKind): ThemeIcon | undefined {
const id = themeIconIds[kind - 1];
return id ? new ThemeIcon(id) : undefined;
}

export function getThemeIcon(kind: VSymbolKind): ThemeIcon | undefined {
const id = themeIconIds[kind];
return id ? new ThemeIcon(id) : undefined;
}
16 changes: 2 additions & 14 deletions src/typeHierarchy/model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { getActiveLanguageClient } from "../extension";
import { LanguageClient } from "vscode-languageclient/node";
import { getRootItem, resolveTypeHierarchy, typeHierarchyDirectionToContextString } from "./util";
import { CancellationToken, commands, workspace } from "vscode";
import { getThemeIcon } from "../themeUtils";

export class TypeHierarchyTreeInput implements SymbolTreeInput<TypeHierarchyItem> {
readonly contextValue: string = "javaTypeHierarchy";
Expand Down Expand Up @@ -124,7 +125,7 @@ class TypeHierarchyTreeDataProvider implements vscode.TreeDataProvider<TypeHiera
const treeItem: vscode.TreeItem = (element === this.model.getBaseItem()) ? new vscode.TreeItem({ label: element.name, highlights: [[0, element.name.length]] }) : new vscode.TreeItem(element.name);
treeItem.contextValue = (element === this.model.getBaseItem() || !element.uri) ? "false" : "true";
treeItem.description = element.detail;
treeItem.iconPath = TypeHierarchyTreeDataProvider.getThemeIcon(element.kind);
treeItem.iconPath = getThemeIcon(element.kind);
treeItem.command = (element.uri) ? {
command: 'vscode.open',
title: 'Open Type Definition Location',
Expand Down Expand Up @@ -248,17 +249,4 @@ class TypeHierarchyTreeDataProvider implements vscode.TreeDataProvider<TypeHiera
expand: false,
};
}

private static themeIconIds = [
'symbol-file', 'symbol-module', 'symbol-namespace', 'symbol-package', 'symbol-class', 'symbol-method',
'symbol-property', 'symbol-field', 'symbol-constructor', 'symbol-enum', 'symbol-interface',
'symbol-function', 'symbol-variable', 'symbol-constant', 'symbol-string', 'symbol-number', 'symbol-boolean',
'symbol-array', 'symbol-object', 'symbol-key', 'symbol-null', 'symbol-enum-member', 'symbol-struct',
'symbol-event', 'symbol-operator', 'symbol-type-parameter'
];

private static getThemeIcon(kind: vscode.SymbolKind): vscode.ThemeIcon | undefined {
const id = TypeHierarchyTreeDataProvider.themeIconIds[kind];
return id ? new vscode.ThemeIcon(id) : undefined;
}
}