diff --git a/README.md b/README.md index fc54b544..958d8df3 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ A lightweight extension to provide additional Java project explorer features. It | Setting Name | Description | Default Value | |---|---|---| -| `java.dependency.showOutline` | Specify whether to show the outline in the dependency viewer. | `true` | +| `java.dependency.showMembers` | Specify whether to show the members in the dependency viewer. | `false` | | `java.dependency.syncWithFolderExplorer` | Specify whether to sync the folder with dependency viewer when browsering files. | `true` | | `java.dependency.autoRefresh` | Specify whether to automatically sync the change from editor to the dependency viewer. | `true` | | `java.dependency.refreshDelay` | The delay time (ms) the auto refresh is invoked when changes are detected. | `2000ms` | 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 2d8b573a..6b763833 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 @@ -43,6 +43,7 @@ import org.eclipse.jdt.core.IJavaProject; import org.eclipse.jdt.core.IPackageFragment; import org.eclipse.jdt.core.IPackageFragmentRoot; +import org.eclipse.jdt.core.IType; import org.eclipse.jdt.core.ITypeRoot; import org.eclipse.jdt.core.JavaCore; import org.eclipse.jdt.core.JavaModelException; @@ -60,7 +61,6 @@ import com.microsoft.jdtls.ext.core.model.NodeKind; import com.microsoft.jdtls.ext.core.model.PackageNode; import com.microsoft.jdtls.ext.core.model.PackageRootNode; -import com.microsoft.jdtls.ext.core.model.TypeRootNode; public class PackageCommand { @@ -122,7 +122,7 @@ public static List resolvePath(List arguments, IProgressMon List result = new ArrayList<>(); URI uri = JDTUtils.toURI(typeRootUri); ITypeRoot typeRoot = ExtUtils.JDT_SCHEME.equals(uri.getScheme()) ? JDTUtils.resolveClassFile(uri) : JDTUtils.resolveCompilationUnit(uri); - if (typeRoot != null) { + if (typeRoot != null && typeRoot.findPrimaryType() != null) { // Add project node: result.add(PackageNode.createNodeForProject(typeRoot)); IPackageFragment packageFragment = (IPackageFragment) typeRoot.getParent(); @@ -135,10 +135,7 @@ public static List resolvePath(List arguments, IProgressMon } result.add(PackageNode.createNodeForPackageFragmentRoot(pkgRoot)); result.add(PackageNode.createNodeForPackageFragment(packageFragment)); - - PackageNode item = new TypeRootNode(typeRoot.getElementName(), typeRoot.getPath().toPortableString(), NodeKind.TYPEROOT, TypeRootNode.K_SOURCE); - item.setUri(JDTUtils.toUri(typeRoot)); - result.add(item); + result.add(PackageNode.createNodeForPrimaryType(typeRoot.findPrimaryType())); } else if (ExtUtils.isJarResourceUri(uri)) { IJarEntryResource resource = ExtUtils.getJarEntryResource(uri); IPackageFragmentRoot pkgRoot = resource.getPackageFragmentRoot(); @@ -349,10 +346,23 @@ private static List getRootTypes(PackageParams query, IProgressMoni IPackageFragment packageFragment = packageRoot .getPackageFragment(PackageNode.DEFAULT_PACKAGE_DISPLAYNAME.equals(query.getPath()) ? "" : query.getPath()); if (packageFragment != null) { - IJavaElement[] types = packageFragment.getChildren(); + List primaryTypes = new ArrayList<>(); + for (IJavaElement element : packageFragment.getChildren()) { + if (element instanceof ITypeRoot) { + // Filter out the inner class files + if (element instanceof IClassFile && element.getElementName().contains("$")) { + continue; + } + IType primaryType = ((ITypeRoot) element).findPrimaryType(); + if (primaryType != null) { + primaryTypes.add(primaryType); + } + } + } Object[] nonJavaResources = packageFragment.getNonJavaResources(); - List rootTypeNodes = Arrays.stream(types).filter(typeRoot -> !typeRoot.getElementName().contains("$")) - .map(PackageNode::createNodeForTypeRoot).collect(Collectors.toList()); + List rootTypeNodes = primaryTypes.stream() + .map(PackageNode::createNodeForPrimaryType) + .collect(Collectors.toList()); if (nonJavaResources.length == 0) { return rootTypeNodes; } @@ -451,7 +461,7 @@ private static List convertToPackageNode(Object[] rootContent, IPac result.add(entry); } else if (root instanceof IClassFile) { IClassFile classFile = (IClassFile) root; - PackageNode entry = new PackageNode(classFile.getElementName(), null, NodeKind.TYPEROOT); + PackageNode entry = new PackageNode(classFile.getElementName(), null, NodeKind.PRIMARYTYPE); entry.setUri(JDTUtils.toUri(classFile)); result.add(entry); } else if (root instanceof JarEntryResource) { diff --git a/jdtls.ext/com.microsoft.jdtls.ext.core/src/com/microsoft/jdtls/ext/core/model/NodeKind.java b/jdtls.ext/com.microsoft.jdtls.ext.core/src/com/microsoft/jdtls/ext/core/model/NodeKind.java index a57b58e7..4211b7f4 100644 --- a/jdtls.ext/com.microsoft.jdtls.ext.core/src/com/microsoft/jdtls/ext/core/model/NodeKind.java +++ b/jdtls.ext/com.microsoft.jdtls.ext.core/src/com/microsoft/jdtls/ext/core/model/NodeKind.java @@ -22,7 +22,7 @@ public enum NodeKind { PACKAGE(5), - TYPEROOT(6), + PRIMARYTYPE(6), FOLDER(7), diff --git a/jdtls.ext/com.microsoft.jdtls.ext.core/src/com/microsoft/jdtls/ext/core/model/PackageNode.java b/jdtls.ext/com.microsoft.jdtls.ext.core/src/com/microsoft/jdtls/ext/core/model/PackageNode.java index fd1c52fe..1b7aa9fe 100644 --- a/jdtls.ext/com.microsoft.jdtls.ext.core/src/com/microsoft/jdtls/ext/core/model/PackageNode.java +++ b/jdtls.ext/com.microsoft.jdtls.ext.core/src/com/microsoft/jdtls/ext/core/model/PackageNode.java @@ -12,7 +12,9 @@ package com.microsoft.jdtls.ext.core.model; import java.net.URI; +import java.util.HashMap; import java.util.List; +import java.util.Map; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IFolder; @@ -20,14 +22,13 @@ import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; -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.IJavaElement; import org.eclipse.jdt.core.IJavaProject; import org.eclipse.jdt.core.IPackageFragment; import org.eclipse.jdt.core.IPackageFragmentRoot; +import org.eclipse.jdt.core.IType; import org.eclipse.jdt.core.JavaCore; import org.eclipse.jdt.core.JavaModelException; import org.eclipse.jdt.ls.core.internal.JDTUtils; @@ -39,6 +40,24 @@ * Represent a PackageNode in the project view. */ public class PackageNode { + + public final static String K_TYPE_KIND = "TypeKind"; + + /** + * Kind constant for a class. + */ + public final static int K_CLASS = 1; + + /** + * Kind constant for an interface. + */ + public final static int K_INTERFACE = 2; + + /** + * Kind constant for an enum. + */ + public final static int K_ENUM = 3; + private static final String REFERENCED_LIBRARIES_CONTAINER_NAME = "Referenced Libraries"; private static final String IMMUTABLE_REFERENCED_LIBRARIES_CONTAINER_NAME = "Referenced Libraries (Read-only)"; @@ -46,8 +65,8 @@ public class PackageNode { public static final String DEFAULT_PACKAGE_DISPLAYNAME = "(default package)"; public static final ContainerNode REFERENCED_LIBRARIES_CONTAINER = new ContainerNode(REFERENCED_LIBRARIES_CONTAINER_NAME, REFERENCED_LIBRARIES_PATH, NodeKind.CONTAINER, IClasspathEntry.CPE_CONTAINER); - public static final ContainerNode IMMUTABLE_REFERENCED_LIBRARIES_CONTAINER = new ContainerNode(IMMUTABLE_REFERENCED_LIBRARIES_CONTAINER_NAME, REFERENCED_LIBRARIES_PATH, - NodeKind.CONTAINER, IClasspathEntry.CPE_CONTAINER); + public static final ContainerNode IMMUTABLE_REFERENCED_LIBRARIES_CONTAINER = new ContainerNode(IMMUTABLE_REFERENCED_LIBRARIES_CONTAINER_NAME, + REFERENCED_LIBRARIES_PATH, NodeKind.CONTAINER, IClasspathEntry.CPE_CONTAINER); /** * The name of the PackageNode @@ -74,6 +93,11 @@ public class PackageNode { */ private NodeKind kind; + /** + * PackageNode metaData + */ + private Map metaData; + /** * PackageNode children list */ @@ -83,6 +107,17 @@ public PackageNode() { } + public Map getMetaData() { + return metaData; + } + + public void setMetaDataValue(String key, Object value) { + if (this.metaData == null) { + this.metaData = new HashMap<>(); + } + this.metaData.put(key, value); + } + public PackageNode(String name, String path, NodeKind kind) { this.name = name; this.path = path; @@ -187,15 +222,23 @@ public static PackageNode createNodeForClasspathEntry(IClasspathEntry classpathE return null; } - public static PackageNode createNodeForTypeRoot(IJavaElement typeRoot) { - PackageNode typeRootNode = new TypeRootNode(typeRoot.getElementName(), typeRoot.getPath().toPortableString(), NodeKind.TYPEROOT, - typeRoot instanceof IClassFile ? TypeRootNode.K_BINARY : TypeRootNode.K_SOURCE); - if (typeRoot instanceof ICompilationUnit) { - typeRootNode.setUri(JDTUtils.toURI((ICompilationUnit) typeRoot)); - } else if (typeRoot instanceof IClassFile) { - typeRootNode.setUri(JDTUtils.toUri((IClassFile) typeRoot)); + public static PackageNode createNodeForPrimaryType(IType type) { + PackageNode primaryTypeNode = new PackageNode(type.getElementName(), type.getPath().toPortableString(), NodeKind.PRIMARYTYPE); + + try { + if (type.isEnum()) { + primaryTypeNode.setMetaDataValue(K_TYPE_KIND, K_ENUM); + } else if (type.isInterface()) { + primaryTypeNode.setMetaDataValue(K_TYPE_KIND, K_INTERFACE); + } else { + primaryTypeNode.setMetaDataValue(K_TYPE_KIND, K_CLASS); + } + } catch (JavaModelException e) { + primaryTypeNode.setMetaDataValue(K_TYPE_KIND, K_CLASS); } - return typeRootNode; + + primaryTypeNode.setUri(JDTUtils.toUri(type.getTypeRoot())); + return primaryTypeNode; } /** diff --git a/jdtls.ext/com.microsoft.jdtls.ext.core/src/com/microsoft/jdtls/ext/core/model/TypeRootNode.java b/jdtls.ext/com.microsoft.jdtls.ext.core/src/com/microsoft/jdtls/ext/core/model/TypeRootNode.java deleted file mode 100644 index 2895b988..00000000 --- a/jdtls.ext/com.microsoft.jdtls.ext.core/src/com/microsoft/jdtls/ext/core/model/TypeRootNode.java +++ /dev/null @@ -1,36 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2018 Microsoft Corporation and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * Microsoft Corporation - initial API and implementation - *******************************************************************************/ - -package com.microsoft.jdtls.ext.core.model; - -public class TypeRootNode extends PackageNode { - - /** - * Kind constant for a source file. - */ - public final static int K_SOURCE = 1; - - /** - * Kind constant for a binary type. - */ - public final static int K_BINARY = 2; - - private int entryKind; - - public TypeRootNode(String name, String path, NodeKind kind, int entryKind) { - super(name, path, kind); - this.entryKind = entryKind; - } - - public int getEntryType() { - return this.entryKind; - } -} diff --git a/package.json b/package.json index 8ad92c21..143f6669 100644 --- a/package.json +++ b/package.json @@ -119,10 +119,10 @@ "type": "object", "title": "%configuration.java.dependency.title%", "properties": { - "java.dependency.showOutline": { + "java.dependency.showMembers": { "type": "boolean", - "description": "%configuration.java.dependency.showOutline%", - "default": true + "description": "%configuration.java.dependency.showMembers%", + "default": false }, "java.dependency.syncWithFolderExplorer": { "type": "boolean", diff --git a/package.nls.json b/package.nls.json index a77d1af7..b368dab8 100644 --- a/package.nls.json +++ b/package.nls.json @@ -14,7 +14,7 @@ "contributes.commands.java.view.package.copyFilePath": "Copy Path", "contributes.commands.java.view.package.copyRelativeFilePath": "Copy Relative Path", "configuration.java.dependency.title": "Java Dependency Configuration", - "configuration.java.dependency.showOutline": "Enable show outline in the Java Dependency explorer", + "configuration.java.dependency.showMembers": "Show the members in the explorer", "configuration.java.dependency.syncWithFolderExplorer": "Synchronize dependency viewer selection with folder explorer", "configuration.java.dependency.autoRefresh": "Synchronize dependency viewer with changes", "configuration.java.dependency.refreshDelay": "The delay time (ms) the auto refresh is invoked when changes are detected", diff --git a/package.nls.zh.json b/package.nls.zh.json index dd06541f..e78ef4f7 100644 --- a/package.nls.zh.json +++ b/package.nls.zh.json @@ -14,7 +14,7 @@ "contributes.commands.java.view.package.copyFilePath": "复制路径", "contributes.commands.java.view.package.copyRelativeFilePath": "复制相对路径", "configuration.java.dependency.title": "Java 依赖管理配置", - "configuration.java.dependency.showOutline": "在 Java 依赖项资源管理器中显示类成员大纲", + "configuration.java.dependency.showMembers": "在 Java 依赖项资源管理器中显示成员", "configuration.java.dependency.syncWithFolderExplorer": "在 Java 依赖项资源管理器中同步关联当前打开的文件", "configuration.java.dependency.autoRefresh": "在 Java 依赖项资源管理器中自动同步修改", "configuration.java.dependency.refreshDelay": "控制Java 依赖项资源管理器刷新的延迟时间 (毫秒)", diff --git a/src/java/nodeData.ts b/src/java/nodeData.ts index aac879c3..62e8f9f9 100644 --- a/src/java/nodeData.ts +++ b/src/java/nodeData.ts @@ -7,11 +7,17 @@ export enum NodeKind { Container = 3, PackageRoot = 4, Package = 5, - TypeRoot = 6, + PrimaryType = 6, Folder = 7, File = 8, } +export enum TypeKind { + Class = 1, + Interface = 2, + Enum = 3, +} + export interface INodeData { name: string; moduleName?: string; @@ -19,4 +25,5 @@ export interface INodeData { uri?: string; kind: NodeKind; children?: any[]; + metaData?: Map; } diff --git a/src/settings.ts b/src/settings.ts index 166ff225..8ebf121a 100644 --- a/src/settings.ts +++ b/src/settings.ts @@ -23,7 +23,7 @@ export class Settings { } })); this.registerConfigurationListener((updatedConfig, oldConfig) => { - if (updatedConfig.showOutline !== oldConfig.showOutline + if (updatedConfig.showMembers !== oldConfig.showMembers || updatedConfig.packagePresentation !== oldConfig.packagePresentation || (updatedConfig.syncWithFolderExplorer !== oldConfig.syncWithFolderExplorer && updatedConfig.syncWithFolderExplorer)) { @@ -93,8 +93,8 @@ export class Settings { } } - public static showOutline(): boolean { - return this._dependencyConfig.get("showOutline"); + public static showMembers(): boolean { + return this._dependencyConfig.get("showMembers"); } public static autoRefresh(): boolean { diff --git a/src/views/PrimaryTypeNode.ts b/src/views/PrimaryTypeNode.ts new file mode 100644 index 00000000..7f473c3e --- /dev/null +++ b/src/views/PrimaryTypeNode.ts @@ -0,0 +1,91 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +import { Command, commands, DocumentSymbol, SymbolInformation, SymbolKind, TextDocument, ThemeIcon, Uri, workspace } from "vscode"; +import { createUuid, sendOperationEnd, sendOperationStart } from "vscode-extension-telemetry-wrapper"; +import { Commands } from "../commands"; +import { INodeData, TypeKind } from "../java/nodeData"; +import { Settings } from "../settings"; +import { DataNode } from "./dataNode"; +import { DocumentSymbolNode } from "./documentSymbolNode"; +import { ExplorerNode } from "./explorerNode"; + +export class PrimaryTypeNode extends DataNode { + + public static K_TYPE_KIND = "TypeKind"; + + constructor(nodeData: INodeData, parent: DataNode) { + super(nodeData, parent); + } + + protected async loadData(): Promise { + if (!this.hasChildren()) { + return null; + } + + return workspace.openTextDocument(Uri.parse(this.nodeData.uri)).then((doc) => { + return this.getSymbols(doc); + }); + } + + protected createChildNodeList(): ExplorerNode[] { + const result: ExplorerNode[] = []; + if (this.nodeData.children && this.nodeData.children.length) { + for (const child of this.nodeData.children) { + const documentSymbol: DocumentSymbol = child as DocumentSymbol; + // Do not show the package declaration + if (documentSymbol.kind === SymbolKind.Package) { + continue; + } + if (documentSymbol.name === this.nodeData.name) { + for (const childSymbol of documentSymbol.children) { + result.push(new DocumentSymbolNode(childSymbol, this)); + } + } + } + } + return result; + } + + protected get iconPath(): string | ThemeIcon { + switch (this.nodeData.metaData[PrimaryTypeNode.K_TYPE_KIND]) { + case TypeKind.Enum: + return new ThemeIcon("symbol-enum"); + case TypeKind.Interface: + return new ThemeIcon("symbol-interface"); + default: + return new ThemeIcon("symbol-class"); + } + } + + protected hasChildren(): boolean { + return Settings.showMembers(); + } + + private async getSymbols(document: TextDocument): Promise { + let error; + const operationId = createUuid(); + const startAt: number = Date.now(); + sendOperationStart(operationId, "vscode.executeDocumentSymbolProvider"); + try { + return await commands.executeCommand( + "vscode.executeDocumentSymbolProvider", + document.uri, + ); + } catch (err) { + error = err; + throw err; + } finally { + const duration = Date.now() - startAt; + sendOperationEnd(operationId, "vscode.executeDocumentSymbolProvider", duration, error); + } + } + + protected get command(): Command { + return { + title: "Open source file content", + command: Commands.VIEW_PACKAGE_OPEN_FILE, + arguments: [this.uri], + }; + } +} diff --git a/src/views/baseSymbolNode.ts b/src/views/baseSymbolNode.ts index aed1b96c..398136f5 100644 --- a/src/views/baseSymbolNode.ts +++ b/src/views/baseSymbolNode.ts @@ -4,7 +4,7 @@ import { Command, DocumentSymbol, Range, SymbolInformation, SymbolKind, ThemeIcon } from "vscode"; import { Commands } from "../commands"; import { ExplorerNode } from "./explorerNode"; -import { TypeRootNode } from "./typeRootNode"; +import { PrimaryTypeNode } from "./PrimaryTypeNode"; export abstract class BaseSymbolNode extends ExplorerNode { @@ -23,7 +23,7 @@ export abstract class BaseSymbolNode extends ExplorerNode { [SymbolKind.Variable, "variable"], ]); - constructor(public readonly symbolInfo: SymbolInformation | DocumentSymbol, private parent: TypeRootNode) { + constructor(public readonly symbolInfo: SymbolInformation | DocumentSymbol, parent: PrimaryTypeNode) { super(parent); } @@ -39,7 +39,7 @@ export abstract class BaseSymbolNode extends ExplorerNode { return { title: "Go to outline", command: Commands.VIEW_PACKAGE_OUTLINE, - arguments: [(this.getParent() as TypeRootNode).uri, this.range], + arguments: [(this.getParent() as PrimaryTypeNode).uri, this.range], }; } diff --git a/src/views/documentSymbolNode.ts b/src/views/documentSymbolNode.ts index 6e0fb62d..32ccc47e 100644 --- a/src/views/documentSymbolNode.ts +++ b/src/views/documentSymbolNode.ts @@ -4,11 +4,11 @@ import { DocumentSymbol, Range, TreeItem, TreeItemCollapsibleState } from "vscode"; import { BaseSymbolNode } from "./baseSymbolNode"; import { ExplorerNode } from "./explorerNode"; -import { TypeRootNode } from "./typeRootNode"; +import { PrimaryTypeNode } from "./PrimaryTypeNode"; export class DocumentSymbolNode extends BaseSymbolNode { - constructor(symbolInfo: DocumentSymbol, parent: TypeRootNode) { + constructor(symbolInfo: DocumentSymbol, parent: PrimaryTypeNode) { super(symbolInfo, parent); } @@ -16,7 +16,7 @@ export class DocumentSymbolNode extends BaseSymbolNode { const res: ExplorerNode[] = []; if (this.symbolInfo && (this.symbolInfo).children && (this.symbolInfo).children.length) { (this.symbolInfo).children.forEach((child) => { - res.push(new DocumentSymbolNode(child, this.getParent() as TypeRootNode)); + res.push(new DocumentSymbolNode(child, this.getParent() as PrimaryTypeNode)); }); } return res; diff --git a/src/views/hierarchicalPackageNode.ts b/src/views/hierarchicalPackageNode.ts index 0a1f2028..82fd779c 100644 --- a/src/views/hierarchicalPackageNode.ts +++ b/src/views/hierarchicalPackageNode.ts @@ -8,8 +8,8 @@ import { DataNode } from "./dataNode"; import { ExplorerNode } from "./explorerNode"; import { FileNode } from "./fileNode"; import { PackageNode } from "./packageNode"; +import { PrimaryTypeNode } from "./PrimaryTypeNode"; import { ProjectNode } from "./projectNode"; -import { TypeRootNode } from "./typeRootNode"; export class HierarchicalPackageNode extends PackageNode { @@ -63,8 +63,10 @@ export class HierarchicalPackageNode extends PackageNode { result.push(new FileNode(nodeData, this)); } else if (nodeData instanceof HierarchicalPackageNodeData) { result.push(new HierarchicalPackageNode(nodeData, this, this._project, this._rootNode)); - } else { - result.push(new TypeRootNode(nodeData, this)); + } else if (nodeData.kind === NodeKind.PrimaryType) { + if (nodeData.metaData && nodeData.metaData[PrimaryTypeNode.K_TYPE_KIND]) { + result.push(new PrimaryTypeNode(nodeData, this)); + } } }); } diff --git a/src/views/hierarchicalPackageRootNode.ts b/src/views/hierarchicalPackageRootNode.ts index 8d4283bb..f6c68e24 100644 --- a/src/views/hierarchicalPackageRootNode.ts +++ b/src/views/hierarchicalPackageRootNode.ts @@ -9,8 +9,8 @@ import { FileNode } from "./fileNode"; import { FolderNode } from "./folderNode"; import { HierarchicalPackageNode } from "./hierarchicalPackageNode"; import { PackageRootNode } from "./packageRootNode"; +import { PrimaryTypeNode } from "./PrimaryTypeNode"; import { ProjectNode } from "./projectNode"; -import { TypeRootNode } from "./typeRootNode"; export class HierarchicalPackageRootNode extends PackageRootNode { @@ -39,8 +39,10 @@ export class HierarchicalPackageRootNode extends PackageRootNode { result.push(new FileNode(data, this)); } else if (data.kind === NodeKind.Folder) { result.push(new FolderNode(data, this, this._project, this)); - } else if (data.kind === NodeKind.TypeRoot) { - result.push(new TypeRootNode(data, this)); + } else if (data.kind === NodeKind.PrimaryType) { + if (data.metaData && data.metaData[PrimaryTypeNode.K_TYPE_KIND]) { + result.push(new PrimaryTypeNode(data, this)); + } } }); } diff --git a/src/views/packageNode.ts b/src/views/packageNode.ts index 9756e79f..5d549658 100644 --- a/src/views/packageNode.ts +++ b/src/views/packageNode.ts @@ -6,7 +6,7 @@ import { INodeData, NodeKind } from "../java/nodeData"; import { DataNode } from "./dataNode"; import { ExplorerNode } from "./explorerNode"; import { FileNode } from "./fileNode"; -import { TypeRootNode } from "./typeRootNode"; +import { PrimaryTypeNode } from "./PrimaryTypeNode"; export class PackageNode extends DataNode { constructor(nodeData: INodeData, parent: DataNode, protected _project: DataNode, protected _rootNode: DataNode) { @@ -29,8 +29,10 @@ export class PackageNode extends DataNode { this.nodeData.children.forEach((nodeData) => { if (nodeData.kind === NodeKind.File) { result.push(new FileNode(nodeData, this)); - } else { - result.push(new TypeRootNode(nodeData, this)); + } else if (nodeData.kind === NodeKind.PrimaryType) { + if (nodeData.metaData && nodeData.metaData[PrimaryTypeNode.K_TYPE_KIND]) { + result.push(new PrimaryTypeNode(nodeData, this)); + } } }); } diff --git a/src/views/packageRootNode.ts b/src/views/packageRootNode.ts index 6d039276..36f6d847 100644 --- a/src/views/packageRootNode.ts +++ b/src/views/packageRootNode.ts @@ -10,8 +10,8 @@ import { ExplorerNode } from "./explorerNode"; import { FileNode } from "./fileNode"; import { FolderNode } from "./folderNode"; import { PackageNode } from "./packageNode"; +import { PrimaryTypeNode } from "./PrimaryTypeNode"; import { ProjectNode } from "./projectNode"; -import { TypeRootNode } from "./typeRootNode"; export class PackageRootNode extends DataNode { @@ -27,15 +27,17 @@ export class PackageRootNode extends DataNode { const result = []; if (this.nodeData.children && this.nodeData.children.length) { this.sort(); - this.nodeData.children.forEach((data) => { + this.nodeData.children.forEach((data: INodeData) => { if (data.kind === NodeKind.Package) { result.push(new PackageNode(data, this, this._project, this)); } else if (data.kind === NodeKind.File) { result.push(new FileNode(data, this)); } else if (data.kind === NodeKind.Folder) { result.push(new FolderNode(data, this, this._project, this)); - } else if (data.kind === NodeKind.TypeRoot) { - result.push(new TypeRootNode(data, this)); + } else if (data.kind === NodeKind.PrimaryType) { + if (data.metaData && data.metaData[PrimaryTypeNode.K_TYPE_KIND]) { + result.push(new PrimaryTypeNode(data, this)); + } } }); } diff --git a/src/views/symbolNode.ts b/src/views/symbolNode.ts index 7d3632b3..144136b2 100644 --- a/src/views/symbolNode.ts +++ b/src/views/symbolNode.ts @@ -5,12 +5,12 @@ import { Range, SymbolInformation, TreeItem, TreeItemCollapsibleState } from "vs import { ITypeRootNodeData } from "../java/typeRootNodeData"; import { BaseSymbolNode } from "./baseSymbolNode"; import { ExplorerNode } from "./explorerNode"; -import { TypeRootNode } from "./typeRootNode"; +import { PrimaryTypeNode } from "./PrimaryTypeNode"; export class SymbolNode extends BaseSymbolNode { private _children: SymbolInformation[]; - constructor(symbolInfo: SymbolInformation, parent: TypeRootNode) { + constructor(symbolInfo: SymbolInformation, parent: PrimaryTypeNode) { super(symbolInfo, parent); } @@ -18,7 +18,7 @@ export class SymbolNode extends BaseSymbolNode { const res: ExplorerNode[] = []; if (this._children && this._children.length) { this._children.forEach((child) => { - res.push(new SymbolNode(child, this.getParent() as TypeRootNode)); + res.push(new SymbolNode(child, this.getParent() as PrimaryTypeNode)); }); } return res; @@ -26,7 +26,7 @@ export class SymbolNode extends BaseSymbolNode { public getTreeItem(): TreeItem | Promise { if (this.symbolInfo) { - const parentData = (this.getParent()).nodeData; + const parentData = (this.getParent()).nodeData; if (parentData && parentData.symbolTree) { this._children = parentData.symbolTree.get(this.symbolInfo.name); } diff --git a/src/views/typeRootNode.ts b/src/views/typeRootNode.ts deleted file mode 100644 index 7519568a..00000000 --- a/src/views/typeRootNode.ts +++ /dev/null @@ -1,105 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT license. - -import { Command, commands, DocumentSymbol, SymbolInformation, TextDocument, ThemeIcon, Uri, workspace } from "vscode"; -import { createUuid, sendOperationEnd, sendOperationStart } from "vscode-extension-telemetry-wrapper"; -import { Commands } from "../commands"; -import { INodeData } from "../java/nodeData"; -import { ITypeRootNodeData, TypeRootKind } from "../java/typeRootNodeData"; -import { Services } from "../services"; -import { Settings } from "../settings"; -import { DataNode } from "./dataNode"; -import { DocumentSymbolNode } from "./documentSymbolNode"; -import { ExplorerNode } from "./explorerNode"; -import { SymbolNode } from "./symbolNode"; - -export class TypeRootNode extends DataNode { - constructor(nodeData: INodeData, parent: DataNode) { - super(nodeData, parent); - } - - protected loadData(): Thenable { - return workspace.openTextDocument(Uri.parse(this.nodeData.uri)).then((doc) => { - return this.getSymbols(doc); - }); - } - - protected createChildNodeList(): ExplorerNode[] { - const data = this.nodeData; - const result: ExplorerNode[] = []; - if (this.nodeData.children && this.nodeData.children.length) { - // After DocumentSymbolProvider api change at - // https://github.com/eclipse/eclipse.jdt.ls/issues/780, the vscode.executeDocumentSymbolProvider - // will return DocumentSymbol[] - if (this.nodeData.children && this.nodeData.children.length && this.nodeData.children[0].hasOwnProperty("children")) { - // if the element in children is DocumentSymbol - this.nodeData.children.forEach((symbolInfo: DocumentSymbol) => { - result.push(new DocumentSymbolNode(symbolInfo, this)); - }); - } else { - // if the element in children is SymbolInformation - 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 | ThemeIcon { - const data = this.nodeData; - if (data.entryKind === TypeRootKind.K_BINARY) { - return ExplorerNode.resolveIconPath("classfile"); - } else { - return Services.context.asAbsolutePath("./images/file-type-java.svg"); - } - } - protected hasChildren(): boolean { - return Settings.showOutline(); - } - - private async getSymbols(document: TextDocument): Promise { - let error; - const operationId = createUuid(); - const startAt: number = Date.now(); - sendOperationStart(operationId, "vscode.executeDocumentSymbolProvider"); - try { - return await commands.executeCommand( - "vscode.executeDocumentSymbolProvider", - document.uri, - ); - } catch (err) { - error = err; - throw err; - } finally { - const duration = Date.now() - startAt; - sendOperationEnd(operationId, "vscode.executeDocumentSymbolProvider", duration, error); - } - } - - 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], - }; - } -}