diff --git a/jdtls.ext/com.microsoft.jdtls.ext.core/src/com/microsoft/jdtls/ext/core/PackageCommand.java b/jdtls.ext/com.microsoft.jdtls.ext.core/src/com/microsoft/jdtls/ext/core/PackageCommand.java index db269c4a..50d413ff 100644 --- a/jdtls.ext/com.microsoft.jdtls.ext.core/src/com/microsoft/jdtls/ext/core/PackageCommand.java +++ b/jdtls.ext/com.microsoft.jdtls.ext.core/src/com/microsoft/jdtls/ext/core/PackageCommand.java @@ -32,6 +32,7 @@ import org.eclipse.jdt.core.IClassFile; import org.eclipse.jdt.core.IClasspathContainer; import org.eclipse.jdt.core.IClasspathEntry; +import org.eclipse.jdt.core.ICompilationUnit; import org.eclipse.jdt.core.IJarEntryResource; import org.eclipse.jdt.core.IJavaElement; import org.eclipse.jdt.core.IJavaProject; @@ -199,6 +200,11 @@ private static List getRootTypes(PackageParams query, IProgressMoni return Arrays.stream(types).filter(typeRoot -> !typeRoot.getElementName().contains("$")).map(typeRoot -> { PackageNode item = new TypeRootNode(typeRoot.getElementName(), typeRoot.getPath().toPortableString(), NodeKind.TYPEROOT, typeRoot instanceof IClassFile ? TypeRootNode.K_BINARY : TypeRootNode.K_SOURCE); + if (typeRoot instanceof ICompilationUnit) { + item.setUri(JDTUtils.toURI((ICompilationUnit) typeRoot)); + } else if (typeRoot instanceof IClassFile) { + item.setUri(JDTUtils.toUri((IClassFile) typeRoot)); + } return item; }).collect(Collectors.toList()); diff --git a/vscode/images/symbols/Class_16x.svg b/vscode/images/symbols/Class_16x.svg new file mode 100644 index 00000000..5ef1c6f8 --- /dev/null +++ b/vscode/images/symbols/Class_16x.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/vscode/images/symbols/Class_inverse_16x.svg b/vscode/images/symbols/Class_inverse_16x.svg new file mode 100644 index 00000000..c43aad29 --- /dev/null +++ b/vscode/images/symbols/Class_inverse_16x.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/vscode/images/symbols/Constant_16x.svg b/vscode/images/symbols/Constant_16x.svg new file mode 100644 index 00000000..ed2a1751 --- /dev/null +++ b/vscode/images/symbols/Constant_16x.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/vscode/images/symbols/Constant_16x_inverse.svg b/vscode/images/symbols/Constant_16x_inverse.svg new file mode 100644 index 00000000..173e427f --- /dev/null +++ b/vscode/images/symbols/Constant_16x_inverse.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/vscode/images/symbols/EnumItem_16x.svg b/vscode/images/symbols/EnumItem_16x.svg new file mode 100644 index 00000000..aa901ec1 --- /dev/null +++ b/vscode/images/symbols/EnumItem_16x.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/vscode/images/symbols/EnumItem_inverse_16x.svg b/vscode/images/symbols/EnumItem_inverse_16x.svg new file mode 100644 index 00000000..79175909 --- /dev/null +++ b/vscode/images/symbols/EnumItem_inverse_16x.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/vscode/images/symbols/Enumerator_16x.svg b/vscode/images/symbols/Enumerator_16x.svg new file mode 100644 index 00000000..e4a9551f --- /dev/null +++ b/vscode/images/symbols/Enumerator_16x.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/vscode/images/symbols/Enumerator_inverse_16x.svg b/vscode/images/symbols/Enumerator_inverse_16x.svg new file mode 100644 index 00000000..d8e9f4f1 --- /dev/null +++ b/vscode/images/symbols/Enumerator_inverse_16x.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/vscode/images/symbols/Field_16x.svg b/vscode/images/symbols/Field_16x.svg new file mode 100644 index 00000000..c6cb5362 --- /dev/null +++ b/vscode/images/symbols/Field_16x.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/vscode/images/symbols/Field_inverse_16x.svg b/vscode/images/symbols/Field_inverse_16x.svg new file mode 100644 index 00000000..5fc48cef --- /dev/null +++ b/vscode/images/symbols/Field_inverse_16x.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/vscode/images/symbols/Interface_16x.svg b/vscode/images/symbols/Interface_16x.svg new file mode 100644 index 00000000..958a7927 --- /dev/null +++ b/vscode/images/symbols/Interface_16x.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/vscode/images/symbols/Interface_inverse_16x.svg b/vscode/images/symbols/Interface_inverse_16x.svg new file mode 100644 index 00000000..f7c2934a --- /dev/null +++ b/vscode/images/symbols/Interface_inverse_16x.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/vscode/images/symbols/LocalVariable_16x_vscode.svg b/vscode/images/symbols/LocalVariable_16x_vscode.svg new file mode 100644 index 00000000..e78894b6 --- /dev/null +++ b/vscode/images/symbols/LocalVariable_16x_vscode.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/vscode/images/symbols/LocalVariable_16x_vscode_inverse.svg b/vscode/images/symbols/LocalVariable_16x_vscode_inverse.svg new file mode 100644 index 00000000..44a44b48 --- /dev/null +++ b/vscode/images/symbols/LocalVariable_16x_vscode_inverse.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/vscode/images/symbols/Method_16x.svg b/vscode/images/symbols/Method_16x.svg new file mode 100644 index 00000000..2be9daa5 --- /dev/null +++ b/vscode/images/symbols/Method_16x.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/vscode/images/symbols/Method_inverse_16x.svg b/vscode/images/symbols/Method_inverse_16x.svg new file mode 100644 index 00000000..d3c2c571 --- /dev/null +++ b/vscode/images/symbols/Method_inverse_16x.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/vscode/images/symbols/Namespace_16x.svg b/vscode/images/symbols/Namespace_16x.svg new file mode 100644 index 00000000..dab07dd5 --- /dev/null +++ b/vscode/images/symbols/Namespace_16x.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/vscode/images/symbols/Namespace_inverse_16x.svg b/vscode/images/symbols/Namespace_inverse_16x.svg new file mode 100644 index 00000000..9b9a44c5 --- /dev/null +++ b/vscode/images/symbols/Namespace_inverse_16x.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/vscode/images/symbols/Property_16x.svg b/vscode/images/symbols/Property_16x.svg new file mode 100644 index 00000000..fb1c74cf --- /dev/null +++ b/vscode/images/symbols/Property_16x.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/vscode/images/symbols/Property_inverse_16x.svg b/vscode/images/symbols/Property_inverse_16x.svg new file mode 100644 index 00000000..f9078189 --- /dev/null +++ b/vscode/images/symbols/Property_inverse_16x.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/vscode/images/symbols/String_16x.svg b/vscode/images/symbols/String_16x.svg new file mode 100644 index 00000000..35e744ce --- /dev/null +++ b/vscode/images/symbols/String_16x.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/vscode/images/symbols/String_inverse_16x.svg b/vscode/images/symbols/String_inverse_16x.svg new file mode 100644 index 00000000..1ac0cf99 --- /dev/null +++ b/vscode/images/symbols/String_inverse_16x.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/vscode/src/commands.ts b/vscode/src/commands.ts index 8c960826..16ae7e21 100644 --- a/vscode/src/commands.ts +++ b/vscode/src/commands.ts @@ -2,18 +2,18 @@ * Commonly used commands */ export namespace Commands { - /** * Execute Workspace Command */ - export const EXECUTE_WORKSPACE_COMMAND = 'java.execute.workspaceCommand'; + export const EXECUTE_WORKSPACE_COMMAND = "java.execute.workspaceCommand"; + export const VIEW_PACKAGE_REFRESH = "java.view.package.refresh"; - export const VIEW_PACKAGE_REFRESH = 'java.view.package.refresh'; + export const VIEW_PACKAGE_OPEN_FILE = "java.view.package.openFile"; - export const VIEW_PACKAGE_OPEN_FILE = 'java.view.package.openFile'; + export const VIEW_PACKAGE_OUTLINE = "java.view.package.outline"; - export const JAVA_GETPROJECTS = 'java.getProjects'; + export const JAVA_GETPROJECTS = "java.getProjects"; - export const JAVA_GETPACKAGEDATA = 'java.getPackageData'; -} \ No newline at end of file + export const JAVA_GETPACKAGEDATA = "java.getPackageData"; +} diff --git a/vscode/src/extension.ts b/vscode/src/extension.ts index 852a6f75..cb6ea5db 100644 --- a/vscode/src/extension.ts +++ b/vscode/src/extension.ts @@ -1,9 +1,9 @@ -import { PackageExplorer } from "./views/packageExplorer"; import { ExtensionContext, window } from "vscode"; import { Services } from "./services"; +import { PackageExplorer } from "./views/packageExplorer"; export function activate(context: ExtensionContext) { Services.initialize(context); - context.subscriptions.push(window.registerTreeDataProvider('javaProjectExplorer', new PackageExplorer(context))); + context.subscriptions.push(window.registerTreeDataProvider("javaProjectExplorer", new PackageExplorer(context))); } diff --git a/vscode/src/java/containerNodeData.ts b/vscode/src/java/containerNodeData.ts index 031775df..2ae89cf3 100644 --- a/vscode/src/java/containerNodeData.ts +++ b/vscode/src/java/containerNodeData.ts @@ -2,10 +2,10 @@ import { INodeData } from "./nodeData"; export enum ContainerEntryKind { /** - * Entry kind constant describing a classpath entry identifying a - * library. A library is a folder or JAR containing package - * fragments consisting of pre-compiled binaries. - */ + * Entry kind constant describing a classpath entry identifying a + * library. A library is a folder or JAR containing package + * fragments consisting of pre-compiled binaries. + */ CPE_LIBRARY = 1, /** @@ -33,7 +33,7 @@ export enum ContainerEntryKind { * * @since 2.0 */ - CPE_CONTAINER = 5 + CPE_CONTAINER = 5, } export interface IContainerNodeData extends INodeData { diff --git a/vscode/src/java/jdtls.ts b/vscode/src/java/jdtls.ts index f7632c71..990ea5d3 100644 --- a/vscode/src/java/jdtls.ts +++ b/vscode/src/java/jdtls.ts @@ -10,4 +10,4 @@ export namespace Jdtls { export function getPackageData(params): Thenable { return commands.executeCommand(Commands.EXECUTE_WORKSPACE_COMMAND, Commands.JAVA_GETPACKAGEDATA, params); } -} \ No newline at end of file +} diff --git a/vscode/src/java/nodeData.ts b/vscode/src/java/nodeData.ts index 0bed3076..32938e88 100644 --- a/vscode/src/java/nodeData.ts +++ b/vscode/src/java/nodeData.ts @@ -7,7 +7,7 @@ export enum NodeKind { Package = 5, TypeRoot = 6, Folder = 7, - File = 8 + File = 8, } export interface INodeData { @@ -16,5 +16,5 @@ export interface INodeData { path?: string; uri?: string; kind: NodeKind; - children?: INodeData[]; -} \ No newline at end of file + children?: any[]; +} diff --git a/vscode/src/java/packageRootNodeData.ts b/vscode/src/java/packageRootNodeData.ts index d98110ad..02f6d914 100644 --- a/vscode/src/java/packageRootNodeData.ts +++ b/vscode/src/java/packageRootNodeData.ts @@ -1,16 +1,16 @@ import { INodeData } from "./nodeData"; export enum PackageRootKind { - /** - * Kind constant for a source path root. Indicates this root - * only contains source files. - */ + /** + * Kind constant for a source path root. Indicates this root + * only contains source files. + */ K_SOURCE = 1, - /** - * Kind constant for a binary path root. Indicates this - * root only contains binary files. - */ - K_BINARY = 2 + /** + * Kind constant for a binary path root. Indicates this + * root only contains binary files. + */ + K_BINARY = 2, } export interface IPackageRootNodeData extends INodeData { diff --git a/vscode/src/java/typeRootNodeData.ts b/vscode/src/java/typeRootNodeData.ts index a0e9062e..a851f1f5 100644 --- a/vscode/src/java/typeRootNodeData.ts +++ b/vscode/src/java/typeRootNodeData.ts @@ -1,18 +1,21 @@ +import { SymbolInformation } from "vscode"; import { INodeData } from "./nodeData"; export enum TypeRootKind { - /** - * Kind constant for a source path root. Indicates this root - * only contains source files. - */ - K_SOURCE = 1, - /** - * Kind constant for a binary path root. Indicates this - * root only contains binary files. - */ - K_BINARY = 2 + /** + * Kind constant for a source path root. Indicates this root + * only contains source files. + */ + K_SOURCE = 1, + /** + * Kind constant for a binary path root. Indicates this + * root only contains binary files. + */ + K_BINARY = 2, } export interface ITypeRootNodeData extends INodeData { - entryKind: TypeRootKind; + entryKind: TypeRootKind; + + symbolTree?: Map; } diff --git a/vscode/src/services.ts b/vscode/src/services.ts index 4adbfee1..9c3b2d26 100644 --- a/vscode/src/services.ts +++ b/vscode/src/services.ts @@ -1,7 +1,7 @@ import { ExtensionContext } from "vscode"; export class Services { - static initialize(context: ExtensionContext) { + public static initialize(context: ExtensionContext) { this._context = context; } @@ -10,4 +10,4 @@ export class Services { static get context() { return this._context; } -} \ No newline at end of file +} diff --git a/vscode/src/views/containerNode.ts b/vscode/src/views/containerNode.ts index 6e010aee..3b18aa7c 100644 --- a/vscode/src/views/containerNode.ts +++ b/vscode/src/views/containerNode.ts @@ -1,7 +1,7 @@ -import { DataNode } from "./dataNode"; +import { Jdtls } from "../java/jdtls"; import { INodeData, NodeKind } from "../java/nodeData"; +import { DataNode } from "./dataNode"; import { ExplorerNode } from "./explorerNode"; -import { Jdtls } from "../java/jdtls"; import { PackageRootNode } from "./packageRootNode"; import { ProjectNode } from "./projectNode"; @@ -23,7 +23,7 @@ export class ContainerNode extends DataNode { return result; } - protected get iconPath() : string { + protected get iconPath(): string { return "./images/library.png"; } } diff --git a/vscode/src/views/dataNode.ts b/vscode/src/views/dataNode.ts index fdd5b7b9..4c01a07f 100644 --- a/vscode/src/views/dataNode.ts +++ b/vscode/src/views/dataNode.ts @@ -1,8 +1,8 @@ -import { ExplorerNode } from "./explorerNode"; +import { ProviderResult, TreeItem, TreeItemCollapsibleState } from "vscode"; import { INodeData } from "../java/nodeData"; -import { ProviderResult, TreeItem, TreeItemCollapsibleState, Uri } from "vscode"; import { Services } from "../services"; +import { ExplorerNode } from "./explorerNode"; export abstract class DataNode extends ExplorerNode { constructor(private _nodeData: INodeData) { @@ -13,6 +13,7 @@ export abstract class DataNode extends ExplorerNode { if (this._nodeData) { const item = new TreeItem(this._nodeData.name, TreeItemCollapsibleState.Collapsed); item.iconPath = Services.context.asAbsolutePath(this.iconPath); + item.command = this.command; return item; } } @@ -41,7 +42,7 @@ export abstract class DataNode extends ExplorerNode { protected abstract get iconPath(): string; - protected abstract loadData(): Thenable; + protected abstract loadData(): Thenable; protected abstract createChildNodeList(): ExplorerNode[]; } diff --git a/vscode/src/views/explorerNode.ts b/vscode/src/views/explorerNode.ts index 9fcd121c..3bd535bd 100644 --- a/vscode/src/views/explorerNode.ts +++ b/vscode/src/views/explorerNode.ts @@ -1,11 +1,14 @@ -import { TreeItem, ProviderResult } from "vscode"; -import { INodeData } from "../java/nodeData"; +import { Command, ProviderResult, TreeItem } from "vscode"; export abstract class ExplorerNode { constructor() { } - abstract getChildren(): ProviderResult; + protected get command(): Command { + return undefined; + } + + public abstract getChildren(): ProviderResult; - abstract getTreeItem(): TreeItem | Promise; -} \ No newline at end of file + public abstract getTreeItem(): TreeItem | Promise; +} diff --git a/vscode/src/views/fileNode.ts b/vscode/src/views/fileNode.ts index 27fa0b12..0e3ad317 100644 --- a/vscode/src/views/fileNode.ts +++ b/vscode/src/views/fileNode.ts @@ -1,5 +1,7 @@ -import { DataNode } from "./dataNode"; +import { Command } from "vscode"; +import { Commands } from "../commands"; import { INodeData } from "../java/nodeData"; +import { DataNode } from "./dataNode"; import { ExplorerNode } from "./explorerNode"; export class FileNode extends DataNode { @@ -15,7 +17,15 @@ export class FileNode extends DataNode { return null; } - protected get iconPath() : string { + protected get iconPath(): string { return "./images/file.png"; } + + protected get command(): Command { + return { + title: "Open file", + command: Commands.VIEW_PACKAGE_OPEN_FILE, + arguments: [this.uri], + }; + } } diff --git a/vscode/src/views/folderNode.ts b/vscode/src/views/folderNode.ts index 9d16bd5c..2847ced1 100644 --- a/vscode/src/views/folderNode.ts +++ b/vscode/src/views/folderNode.ts @@ -1,9 +1,9 @@ -import { DataNode } from "./dataNode"; -import { INodeData, NodeKind } from "../java/nodeData"; import { Jdtls } from "../java/jdtls"; -import { ProjectNode } from "./projectNode"; +import { INodeData, NodeKind } from "../java/nodeData"; +import { DataNode } from "./dataNode"; import { ExplorerNode } from "./explorerNode"; import { FileNode } from "./fileNode"; +import { ProjectNode } from "./projectNode"; export class FolderNode extends DataNode { constructor(nodeData: INodeData, private _project: ProjectNode, private _rootNode: DataNode) { @@ -28,7 +28,7 @@ export class FolderNode extends DataNode { return result; } - protected get iconPath() : string { + protected get iconPath(): string { return "./images/folder.png"; } -} \ No newline at end of file +} diff --git a/vscode/src/views/packageExplorer.ts b/vscode/src/views/packageExplorer.ts index c07896d2..fde079ba 100644 --- a/vscode/src/views/packageExplorer.ts +++ b/vscode/src/views/packageExplorer.ts @@ -1,26 +1,51 @@ -import * as vscode from 'vscode'; -import { Commands } from '../commands'; -import { ExplorerNode } from './explorerNode'; -import { WorkspaceNode } from './workspaceNode'; -import { NodeKind } from '../java/nodeData'; - -export class PackageExplorer implements vscode.TreeDataProvider { - constructor(public readonly context: vscode.ExtensionContext) { - context.subscriptions.push(vscode.commands.registerCommand(Commands.VIEW_PACKAGE_REFRESH, this.refresh, this)); - context.subscriptions.push(vscode.commands.registerCommand(Commands.VIEW_PACKAGE_OPEN_FILE, this.openFile, this)); - } +import { + commands, Event, EventEmitter, ExtensionContext, ProviderResult, Range, Selection, + TextEditorRevealType, TreeDataProvider, TreeItem, Uri, window, workspace, +} from "vscode"; +import { Commands } from "../commands"; +import { NodeKind } from "../java/nodeData"; +import { ExplorerNode } from "./explorerNode"; +import { WorkspaceNode } from "./workspaceNode"; + +export class PackageExplorer implements TreeDataProvider { + + private _onDidChangeTreeData: EventEmitter = new EventEmitter(); + + // tslint:disable-next-line:member-ordering + public onDidChangeTreeData: Event = this._onDidChangeTreeData.event; private _rootItems: ExplorerNode[] = null; - private _onDidChangeTreeData: vscode.EventEmitter = new vscode.EventEmitter(); + constructor(public readonly context: ExtensionContext) { + context.subscriptions.push(commands.registerCommand(Commands.VIEW_PACKAGE_REFRESH, this.refresh, this)); + context.subscriptions.push(commands.registerCommand(Commands.VIEW_PACKAGE_OPEN_FILE, this.openFile, this)); + context.subscriptions.push(commands.registerCommand(Commands.VIEW_PACKAGE_OUTLINE, this.goToOutline, this)); + } + + public refresh() { + this._rootItems = null; + this._onDidChangeTreeData.fire(); + } - public readonly onDidChangeTreeData: vscode.Event = this._onDidChangeTreeData.event; + public openFile(uri: string) { + return workspace.openTextDocument(Uri.parse(uri)).then((res) => { + return window.showTextDocument(res); + }); + } - getTreeItem(element: ExplorerNode): vscode.TreeItem | Thenable { + public goToOutline(uri: string, range: Range): Thenable<{}> { + return this.openFile(uri).then((editor) => { + editor.revealRange(range, TextEditorRevealType.Default); + editor.selection = new Selection(range.start, range.start); + return commands.executeCommand("workbench.action.focusActiveEditorGroup"); + }); + } + + public getTreeItem(element: ExplorerNode): TreeItem | Thenable { return element.getTreeItem(); } - getChildren(element?: ExplorerNode): vscode.ProviderResult { + public getChildren(element?: ExplorerNode): ProviderResult { if (!this._rootItems || !element) { this._rootItems = this.getRootNodes(); return this._rootItems; @@ -29,25 +54,14 @@ export class PackageExplorer implements vscode.TreeDataProvider { } } - public refresh() { - this._rootItems = null; - this._onDidChangeTreeData.fire(); - } - - public openFile(query) { - vscode.workspace.openTextDocument(vscode.Uri.parse(query.path)).then((res) => { - vscode.window.showTextDocument(res); - }); - } - private getRootNodes() { const result: ExplorerNode[] = new Array(); - const folders = vscode.workspace.workspaceFolders; + const folders = workspace.workspaceFolders; if (folders && folders.length) { folders.forEach((folder) => result.push(new WorkspaceNode({ name: folder.name, uri: folder.uri.toString(), - kind: NodeKind.Workspace + kind: NodeKind.Workspace, }))); } return result; diff --git a/vscode/src/views/packageNode.ts b/vscode/src/views/packageNode.ts index 4e6b9c39..d94c68cf 100644 --- a/vscode/src/views/packageNode.ts +++ b/vscode/src/views/packageNode.ts @@ -1,9 +1,8 @@ -import { ExplorerNode } from "./explorerNode"; +import { Jdtls } from "../java/jdtls"; import { INodeData, NodeKind } from "../java/nodeData"; import { DataNode } from "./dataNode"; -import { ProjectNode } from "./projectNode"; -import { Jdtls } from "../java/jdtls"; +import { ExplorerNode } from "./explorerNode"; import { TypeRootNode } from "./typeRootNode"; export class PackageNode extends DataNode { @@ -12,7 +11,12 @@ export class PackageNode extends DataNode { } protected loadData(): Thenable { - return Jdtls.getPackageData({ kind: NodeKind.Package, projectUri: this._project.nodeData.uri, path: this.nodeData.name, rootPath: this._rootNode.path }); + return Jdtls.getPackageData({ + kind: NodeKind.Package, + projectUri: this._project.nodeData.uri, + path: this.nodeData.name, + rootPath: this._rootNode.path, + }); } protected createChildNodeList(): ExplorerNode[] { diff --git a/vscode/src/views/packageRootNode.ts b/vscode/src/views/packageRootNode.ts index 25111fdb..1e9d30e1 100644 --- a/vscode/src/views/packageRootNode.ts +++ b/vscode/src/views/packageRootNode.ts @@ -1,14 +1,13 @@ -import { DataNode } from "./dataNode"; -import { INodeData, NodeKind } from "../java/nodeData"; import { Jdtls } from "../java/jdtls"; +import { INodeData, NodeKind } from "../java/nodeData"; +import { IPackageRootNodeData, PackageRootKind } from "../java/packageRootNodeData"; +import { DataNode } from "./dataNode"; import { ExplorerNode } from "./explorerNode"; -import { TypeRootNode } from "./typeRootNode"; -import { FolderNode } from "./folderNode"; import { FileNode } from "./fileNode"; +import { FolderNode } from "./folderNode"; import { PackageNode } from "./packageNode"; import { ProjectNode } from "./projectNode"; -import { IPackageRootNodeData, PackageRootKind } from "../java/packageRootNodeData"; -import { IContainerNodeData } from "../java/containerNodeData"; +import { TypeRootNode } from "./typeRootNode"; export class PackageRootNode extends DataNode { @@ -46,4 +45,4 @@ export class PackageRootNode extends DataNode { return "./images/packagefolder.png"; } } -} \ No newline at end of file +} diff --git a/vscode/src/views/projectNode.ts b/vscode/src/views/projectNode.ts index 81a9c5e0..cb33d5fe 100644 --- a/vscode/src/views/projectNode.ts +++ b/vscode/src/views/projectNode.ts @@ -1,11 +1,10 @@ -import { ExplorerNode } from "./explorerNode"; -import { DataNode } from "./dataNode"; -import { TreeItem, TreeItemCollapsibleState } from "vscode"; -import { INodeData, NodeKind } from "../java/nodeData"; +import { ContainerEntryKind, IContainerNodeData } from "../java/containerNodeData"; import { Jdtls } from "../java/jdtls"; +import { INodeData, NodeKind } from "../java/nodeData"; import { ContainerNode } from "./containerNode"; +import { DataNode } from "./dataNode"; +import { ExplorerNode } from "./explorerNode"; import { PackageRootNode } from "./packageRootNode"; -import { IContainerNodeData, ContainerEntryKind } from "../java/containerNodeData"; export class ProjectNode extends DataNode { @@ -26,7 +25,7 @@ export class ProjectNode extends DataNode { } }); if (sourceContainer.length > 0) { - return Promise.all(sourceContainer.map(c => Jdtls.getPackageData({ kind: NodeKind.Container, projectUri: this.uri, path: c.path }))) + return Promise.all(sourceContainer.map((c) => Jdtls.getPackageData({ kind: NodeKind.Container, projectUri: this.uri, path: c.path }))) .then((rootPackages) => { result = result.concat(...rootPackages); return result; diff --git a/vscode/src/views/symbolNode.ts b/vscode/src/views/symbolNode.ts new file mode 100644 index 00000000..04243c3d --- /dev/null +++ b/vscode/src/views/symbolNode.ts @@ -0,0 +1,73 @@ +import { Command, SymbolInformation, SymbolKind, TreeItem, TreeItemCollapsibleState } from "vscode"; +import { Commands } from "../commands"; +import { ITypeRootNodeData } from "../java/typeRootNodeData"; +import { Services } from "../services"; +import { ExplorerNode } from "./explorerNode"; +import { TypeRootNode } from "./typeRootNode"; + +export class SymbolNode extends ExplorerNode { + + private static _iconMap: Map = new Map([ + [SymbolKind.Class, "Class"], + [SymbolKind.Interface, "Interface"], + [SymbolKind.Enum, "Enumerator"], + [SymbolKind.EnumMember, "EnumItem"], + [SymbolKind.Constant, "Constant"], + [SymbolKind.Method, "Method"], + [SymbolKind.Function, "Method"], + [SymbolKind.Constructor, "Method"], + [SymbolKind.Field, "Field"], + [SymbolKind.Property, "Property"], + [SymbolKind.Variable, "LocalVariable"], + [SymbolKind.Constant, "Constant"], + + ]); + + private _children: SymbolInformation[]; + + constructor(public readonly symbolInfo: SymbolInformation, private _prarent: TypeRootNode) { + super(); + } + + public getChildren(): ExplorerNode[] | Thenable { + const res: ExplorerNode[] = []; + if (this._children && this._children.length) { + this._children.forEach((child) => { + res.push(new SymbolNode(child, this._prarent)); + }); + } + return res; + } + + public getTreeItem(): TreeItem | Promise { + if (this.symbolInfo) { + const parentData = this._prarent.nodeData; + if (parentData && parentData.symbolTree) { + this._children = parentData.symbolTree.get(this.symbolInfo.name); + } + const item = new TreeItem(this.symbolInfo.name, + (this._children && this._children.length) ? TreeItemCollapsibleState.Collapsed : TreeItemCollapsibleState.None); + item.iconPath = this.iconPath; + item.command = this.command; + return item; + } + } + + private get iconPath(): any { + if (SymbolNode._iconMap.has(this.symbolInfo.kind)) { + const iconFileName = SymbolNode._iconMap.get(this.symbolInfo.kind); + return { + light: Services.context.asAbsolutePath(`./images/symbols/${iconFileName}_16x.svg`), + dark: Services.context.asAbsolutePath(`./images/symbols/${iconFileName}_inverse_16x.svg`), + }; + } + } + + protected get command(): Command { + return { + title: "Go to outline", + command: Commands.VIEW_PACKAGE_OUTLINE, + arguments: [this._prarent.uri, this.symbolInfo.location.range], + }; + } +} diff --git a/vscode/src/views/typeRootNode.ts b/vscode/src/views/typeRootNode.ts index a2098226..3780e8a1 100644 --- a/vscode/src/views/typeRootNode.ts +++ b/vscode/src/views/typeRootNode.ts @@ -1,30 +1,35 @@ +import { Command, commands, SymbolInformation, TextDocument, Uri, workspace } from "vscode"; +import { Commands } from "../commands"; import { INodeData } from "../java/nodeData"; -import { ExplorerNode } from "./explorerNode"; -import { DataNode } from "./dataNode"; -import { TreeItem, TreeItemCollapsibleState } from "vscode"; -import { Services } from "../services"; import { ITypeRootNodeData, TypeRootKind } from "../java/typeRootNodeData"; +import { DataNode } from "./dataNode"; +import { ExplorerNode } from "./explorerNode"; +import { SymbolNode } from "./symbolNode"; export class TypeRootNode extends DataNode { constructor(nodeData: INodeData) { super(nodeData); } - - public getTreeItem(): TreeItem | Promise { - if (this.nodeData) { - const item = new TreeItem(this.nodeData.name, TreeItemCollapsibleState.None); - item.iconPath = Services.context.asAbsolutePath(this.iconPath); - return item; - } - } - - protected loadData(): Thenable { - return null; + protected loadData(): Thenable { + return workspace.openTextDocument(Uri.parse(this.nodeData.uri)).then((doc) => { + return this.getSymbols(doc); + }); } protected createChildNodeList(): ExplorerNode[] { - return null; + const data = this.nodeData; + const result: ExplorerNode[] = []; + if (this.nodeData.children && this.nodeData.children.length) { + data.symbolTree = this.buildSymbolTree(this.nodeData.children); + const directChildren = data.symbolTree.get(this.nodeData.name); + if (directChildren && directChildren.length) { + directChildren.forEach((symbolInfo) => { + result.push(new SymbolNode(symbolInfo, this)); + }); + } + } + return result; } protected get iconPath(): string { @@ -35,4 +40,32 @@ export class TypeRootNode extends DataNode { return "./images/file_type_java.svg"; } } -} \ No newline at end of file + + private getSymbols(document: TextDocument): Thenable { + return commands.executeCommand( + "vscode.executeDocumentSymbolProvider", + document.uri, + ); + } + + private buildSymbolTree(symbols: SymbolInformation[]): Map { + const res = new Map(); + + symbols.forEach((symbol) => { + if (!res.has(symbol.containerName)) { + res.set(symbol.containerName, []); + } + res.get(symbol.containerName).push(symbol); + }); + + return res; + } + + protected get command(): Command { + return { + title: "Open source file content", + command: Commands.VIEW_PACKAGE_OPEN_FILE, + arguments: [this.uri], + }; + } +} diff --git a/vscode/src/views/workspaceNode.ts b/vscode/src/views/workspaceNode.ts index 0219cdd6..796d66b2 100644 --- a/vscode/src/views/workspaceNode.ts +++ b/vscode/src/views/workspaceNode.ts @@ -1,8 +1,7 @@ +import { Jdtls } from "../java/jdtls"; +import { INodeData } from "../java/nodeData"; import { DataNode } from "./dataNode"; -import { INodeData, NodeKind } from "../java/nodeData"; import { ExplorerNode } from "./explorerNode"; -import { Jdtls } from "../java/jdtls"; -import { TreeItem, TreeItemCollapsibleState } from "vscode"; import { ProjectNode } from "./projectNode"; export class WorkspaceNode extends DataNode { @@ -24,7 +23,7 @@ export class WorkspaceNode extends DataNode { return result; } - protected get iconPath() : string { + protected get iconPath(): string { return "./images/project.gif"; } } diff --git a/vscode/tslint.json b/vscode/tslint.json new file mode 100644 index 00000000..6f8577d3 --- /dev/null +++ b/vscode/tslint.json @@ -0,0 +1,46 @@ +{ + "extends": "tslint:latest", + "rules": { + "variable-name": [ + true, + "allow-leading-underscore" + ], + "no-unused-expression": true, + "no-duplicate-variable": true, + "max-classes-per-file": [ + false + ], + "no-implicit-dependencies": [ + true, + "dev" + ], + "no-empty": false, + "object-literal-sort-keys": false, + "curly": true, + "class-name": true, + "whitespace": [ + true, + "check-branch", + "check-decl", + "check-operator", + "check-module", + "check-separator", + "check-type" + ], + "semicolon": [ + true + ], + "triple-equals": true, + "max-line-length": [ + true, + 150 + ], + "no-angle-bracket-type-assertion": false, + "no-console": [ + true, + "log", + "error" + ], + "no-namespace": false + } +}