Skip to content

Commit

Permalink
Support right click context for viewer nodes (#208)
Browse files Browse the repository at this point in the history
* Support URI for nodes created from classpath entry

* Support URI for PackageRootNode

* Support URI for PackageFragment

* Support Right Click Context in Client Side

* Change description for `revealFileInOS`

* Hide right-click-context commands from command palette

* Add context value for testing uri

* Extract detecting container uri as util method

* Fix getContainerURI NPE
  • Loading branch information
Vigilans authored and testforstephen committed Dec 26, 2019
1 parent 26c5920 commit b87c7b5
Show file tree
Hide file tree
Showing 9 changed files with 125 additions and 21 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,16 @@
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jdt.core.IClasspathContainer;
import org.eclipse.jdt.core.IJarEntryResource;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.internal.core.JarEntryDirectory;
import org.eclipse.jdt.internal.core.JarEntryFile;
import org.eclipse.jdt.launching.JavaRuntime;
import org.eclipse.jdt.ls.core.internal.JavaLanguageServerPlugin;

public final class ExtUtils {
Expand Down Expand Up @@ -104,6 +107,18 @@ public static IPath removeProjectSegment(String projectElementName, IPath path)
return path;
}

public static URI getContainerURI(IJavaProject javaProject, IClasspathContainer container) throws CoreException {
switch (container.getKind()) {
case IClasspathContainer.K_DEFAULT_SYSTEM: // JRE Container
case IClasspathContainer.K_SYSTEM:
return JavaRuntime.getVMInstall(javaProject).getInstallLocation().toURI();
case IClasspathContainer.K_APPLICATION: // Plugin Container, Maven Container, etc
return null; // TODO: find out a good way to detect these containers' uri
default: // Persistent container (e.g. /src/main/java)
return container.getPath().toFile().toURI();
}
}

private static JarEntryFile findFileInJar(JarEntryDirectory directory, String path) {
for (IJarEntryResource child : directory.getChildren()) {
if (child instanceof JarEntryFile && child.getFullPath().toPortableString().equals(path)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -175,9 +175,9 @@ public static List<PackageNode> resolvePath(List<Object> arguments, IProgressMon
IPackageFragmentRoot pkgRoot = (IPackageFragmentRoot) packageFragment.getParent();
PackageNode rootNode = null;

rootNode = new PackageRootNode(
rootNode = new PackageRootNode(pkgRoot,
ExtUtils.removeProjectSegment(packageFragment.getJavaProject().getElementName(), pkgRoot.getPath()).toPortableString(),
pkgRoot.getPath().toPortableString(), NodeKind.PACKAGEROOT, pkgRoot.getKind());
NodeKind.PACKAGEROOT);

result.add(PackageNode.createNodeForProject(packageFragment));
result.add(rootNode);
Expand Down Expand Up @@ -209,8 +209,8 @@ private static List<PackageNode> getParentAncestorNodes(IResource element) throw
IJavaElement javaElement = JavaCore.create(element);
if (javaElement instanceof IPackageFragmentRoot) {
IPackageFragmentRoot pkgRoot = (IPackageFragmentRoot) javaElement;
nodeList.add(0, new PackageRootNode(element.getProjectRelativePath().toPortableString(), pkgRoot.getPath().toPortableString(),
NodeKind.PACKAGEROOT, pkgRoot.getKind()));
nodeList.add(0, new PackageRootNode(pkgRoot,
element.getProjectRelativePath().toPortableString(), NodeKind.PACKAGEROOT));
nodeList.add(0, PackageNode.createNodeForProject(javaElement));
return nodeList;
} else if (javaElement instanceof IPackageFragment) {
Expand Down Expand Up @@ -280,8 +280,7 @@ private static List<PackageNode> getPackageFragmentRoots(PackageParams query, IP
if (fragmentRoot.getKind() == IPackageFragmentRoot.K_SOURCE) {
displayName = ExtUtils.removeProjectSegment(javaProject.getElementName(), fragmentRoot.getPath()).toPortableString();
}
PackageRootNode node = new PackageRootNode(displayName, fragmentRoot.getPath().toPortableString(), NodeKind.PACKAGEROOT,
fragmentRoot.getKind());
PackageRootNode node = new PackageRootNode(fragmentRoot, displayName, NodeKind.PACKAGEROOT);
children.add(node);
if (fragmentRoot instanceof JrtPackageFragmentRoot) {
node.setModuleName(fragmentRoot.getModuleDescription().getElementName());
Expand Down Expand Up @@ -440,7 +439,14 @@ private static List<PackageNode> convertToPackageNode(Object[] rootContent, IPac
List<PackageNode> result = new ArrayList<>();
for (Object root : rootContent) {
if (root instanceof IPackageFragment) {
result.add(PackageNode.createNodeForPackageFragment((IPackageFragment) root));
IPackageFragment fragment = (IPackageFragment) root;
PackageNode entry = PackageNode.createNodeForPackageFragment(fragment);
if (fragment.getResource() != null) {
entry.setUri(fragment.getResource().getLocationURI().toString());
} else {
entry.setUri(fragment.getPath().toFile().toURI().toString());
}
result.add(entry);
} else if (root instanceof IClassFile) {
IClassFile classFile = (IClassFile) root;
PackageNode entry = new PackageNode(classFile.getElementName(), null, NodeKind.TYPEROOT);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

package com.microsoft.jdtls.ext.core.model;

import java.net.URI;
import java.util.List;

import org.eclipse.core.resources.IFile;
Expand Down Expand Up @@ -133,11 +134,11 @@ public static PackageNode createNodeForPackageFragmentRoot(IPackageFragmentRoot
if (entry.getEntryKind() == IClasspathEntry.CPE_VARIABLE) {
return createNodeForClasspathVariable(entry);
} else {
return new PackageRootNode(pkgRoot.getElementName(), pkgRoot.getPath().toPortableString(), NodeKind.PACKAGEROOT, pkgRoot.getKind());
return new PackageRootNode(pkgRoot, pkgRoot.getElementName(), NodeKind.PACKAGEROOT);
}
} else {
return new PackageRootNode(ExtUtils.removeProjectSegment(pkgRoot.getJavaProject().getElementName(), pkgRoot.getPath()).toPortableString(),
pkgRoot.getPath().toPortableString(), NodeKind.PACKAGEROOT, pkgRoot.getKind());
return new PackageRootNode(pkgRoot,
ExtUtils.removeProjectSegment(pkgRoot.getJavaProject().getElementName(), pkgRoot.getPath()).toPortableString(), NodeKind.PACKAGEROOT);
}
}

Expand All @@ -161,17 +162,21 @@ public static PackageNode createNodeForClasspathEntry(IClasspathEntry classpathE
container = JavaCore.getClasspathContainer(entry.getPath(), javaProject);
}
if (container != null) {
switch (nodeKind) {
case CONTAINER:
return new ContainerNode(container.getDescription(), container.getPath().toPortableString(), nodeKind, entry.getEntryKind());
case PACKAGEROOT:
PackageNode node = null;
if (nodeKind == NodeKind.CONTAINER) {
node = new ContainerNode(container.getDescription(), container.getPath().toPortableString(), nodeKind, entry.getEntryKind());
final URI containerURI = ExtUtils.getContainerURI(javaProject, container);
node.setUri(containerURI != null ? containerURI.toString() : null);
} else if (nodeKind == NodeKind.PACKAGEROOT) { // ClasspathEntry for referenced jar files
// Use package name as package root name
String[] pathSegments = container.getPath().segments();
return new PackageRootNode(pathSegments[pathSegments.length - 1], container.getPath().toPortableString(), nodeKind,
IPackageFragmentRoot.K_BINARY);
default:
return null;
node = new PackageRootNode(
pathSegments[pathSegments.length - 1],
container.getPath().toPortableString(),
container.getPath().toFile().toURI().toString(),
nodeKind, IPackageFragmentRoot.K_BINARY);
}
return node;
}
} catch (CoreException e) {
JdtlsExtActivator.logException("Problems when convert classpath entry to package node ", e);
Expand Down Expand Up @@ -201,7 +206,8 @@ public static PackageNode createNodeForClasspathVariable(IClasspathEntry classpa
IClasspathEntry entry = JavaCore.getResolvedClasspathEntry(classpathEntry);
String name = classpathEntry.getPath().toPortableString();
String path = entry.getPath().toPortableString();
return new PackageRootNode(name, path, NodeKind.PACKAGEROOT, IPackageFragmentRoot.K_BINARY);
String uri = entry.getPath().toFile().toURI().toString();
return new PackageRootNode(name, path, uri, NodeKind.PACKAGEROOT, IPackageFragmentRoot.K_BINARY);
}

public String getName() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,30 @@

import java.util.Map;

import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.core.JavaModelException;

public class PackageRootNode extends PackageNode {

private int entryKind;

private Map<String, String> attributes;

public PackageRootNode(String name, String path, NodeKind kind, int entryKind) {
public PackageRootNode(String name, String path, String uri, NodeKind kind, int entryKind) {
super(name, path, kind);
this.setUri(uri);
this.entryKind = entryKind;
}

public PackageRootNode(IPackageFragmentRoot pkgRoot, String name, NodeKind kind) throws JavaModelException {
this(name, pkgRoot.getPath().toPortableString(), null, kind, pkgRoot.getKind());
if (pkgRoot.getResource() != null) {
this.setUri(pkgRoot.getResource().getLocationURI().toString());
} else {
this.setUri(pkgRoot.getPath().toFile().toURI().toString());
}
}

public int getEntryType() {
return this.entryKind;
}
Expand Down
48 changes: 47 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
"explorer"
],
"engines": {
"vscode": "^1.30.0"
"vscode": "^1.31.0"
},
"repository": {
"type": "git",
Expand Down Expand Up @@ -83,6 +83,21 @@
"dark": "images/dark/icon-link.svg",
"light": "images/light/icon-link.svg"
}
},
{
"command": "java.view.package.revealFileInOS",
"title": "%contributes.commands.java.view.package.revealFileInOS%",
"category": "Java"
},
{
"command": "java.view.package.copyFilePath",
"title": "%contributes.commands.java.view.package.copyFilePath%",
"category": "Java"
},
{
"command": "java.view.package.copyRelativeFilePath",
"title": "%contributes.commands.java.view.package.copyRelativeFilePath%",
"category": "Java"
}
],
"configuration": {
Expand Down Expand Up @@ -121,6 +136,20 @@
}
},
"menus": {
"commandPalette": [
{
"command": "java.view.package.revealFileInOS",
"when": "never"
},
{
"command": "java.view.package.copyFilePath",
"when": "never"
},
{
"command": "java.view.package.copyRelativeFilePath",
"when": "never"
}
],
"view/title": [
{
"command": "java.view.package.refresh",
Expand All @@ -147,6 +176,23 @@
"when": "view == javaDependencyExplorer && config.java.dependency.syncWithFolderExplorer == true",
"group": "navigation@0"
}
],
"view/item/context": [
{
"command": "java.view.package.revealFileInOS",
"when": "view == javaDependencyExplorer && viewItem =~ /java:.*?\\+uri/",
"group": "@1"
},
{
"command": "java.view.package.copyFilePath",
"when": "view == javaDependencyExplorer && viewItem =~ /java:.*?\\+uri/",
"group": "@2"
},
{
"command": "java.view.package.copyRelativeFilePath",
"when": "view == javaDependencyExplorer && viewItem =~ /java:.*?\\+uri/",
"group": "@2"
}
]
},
"views": {
Expand Down
3 changes: 3 additions & 0 deletions package.nls.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
"contributes.commands.java.view.package.changeToHierarchicalPackageView":"Change to hierarchical package representation",
"contributes.commands.java.view.package.linkWithFolderExplorer":"Synchronize dependency viewer selection with folder explorer",
"contributes.commands.java.view.package.unlinkWithFolderExplorer":"Desynchronize dependency viewer selection with folder explorer",
"contributes.commands.java.view.package.revealFileInOS": "Reveal In Explorer",
"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.syncWithFolderExplorer": "Synchronize dependency viewer selection with folder explorer",
Expand Down
3 changes: 3 additions & 0 deletions package.nls.zh.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
"contributes.commands.java.view.package.changeToHierarchicalPackageView":"将 Java 包显示方式切换为分层显示",
"contributes.commands.java.view.package.linkWithFolderExplorer":"开启 Java 依赖项资源管理器与当前浏览文件的关联",
"contributes.commands.java.view.package.unlinkWithFolderExplorer":"关闭 Java 依赖项资源管理器与当前浏览文件的关联",
"contributes.commands.java.view.package.revealFileInOS": "打开所在的文件夹",
"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.syncWithFolderExplorer": "在 Java 依赖项资源管理器中同步关联当前打开的文件",
Expand Down
6 changes: 6 additions & 0 deletions src/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@ export namespace Commands {

export const VIEW_PACKAGE_OUTLINE = "java.view.package.outline";

export const VIEW_PACKAGE_REVEAL_FILE_OS = "java.view.package.revealFileInOS";

export const VIEW_PACKAGE_COPY_FILE_PATH = "java.view.package.copyFilePath";

export const VIEW_PACKAGE_COPY_RELATIVE_FILE_PATH = "java.view.package.copyRelativeFilePath";

export const JAVA_PROJECT_CREATE = "java.project.create";

export const JAVA_PROJECT_LIST = "java.project.list";
Expand Down
6 changes: 6 additions & 0 deletions src/views/dependencyDataProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,12 @@ export class DependencyDataProvider implements TreeDataProvider<ExplorerNode> {

constructor(public readonly context: ExtensionContext) {
context.subscriptions.push(commands.registerCommand(Commands.VIEW_PACKAGE_REFRESH, (debounce?: boolean) => this.refreshWithLog(debounce)));
context.subscriptions.push(commands.registerCommand(Commands.VIEW_PACKAGE_REVEAL_FILE_OS,
(node: INodeData) => commands.executeCommand("revealFileInOS", Uri.parse(node.uri))));
context.subscriptions.push(commands.registerCommand(Commands.VIEW_PACKAGE_COPY_FILE_PATH,
(node: INodeData) => commands.executeCommand("copyFilePath", Uri.parse(node.uri))));
context.subscriptions.push(commands.registerCommand(Commands.VIEW_PACKAGE_COPY_RELATIVE_FILE_PATH,
(node: INodeData) => commands.executeCommand("copyRelativeFilePath", Uri.parse(node.uri))));
context.subscriptions.push(commands.registerCommand(Commands.VIEW_PACKAGE_OPEN_FILE,
instrumentOperation(Commands.VIEW_PACKAGE_OPEN_FILE, (_operationId, uri) => this.openFile(uri))));
context.subscriptions.push(commands.registerCommand(Commands.VIEW_PACKAGE_OUTLINE,
Expand Down

0 comments on commit b87c7b5

Please sign in to comment.