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 e45bd645..7353d02a 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 @@ -67,6 +67,13 @@ public class PackageCommand { private static final String DEFAULT_PACKAGE_DISPLAYNAME = "(default package)"; + private static final String REFERENCED_LIBRARIES_PATH = "REFERENCED_LIBRARIES_PATH"; + + private static final String REFERENCED_LIBRARIES_CONTAINER_NAME = "Referenced Libraries"; + + private static final ContainerNode REFERENCED_LIBRARIES_CONTAINER = new ContainerNode(REFERENCED_LIBRARIES_CONTAINER_NAME, REFERENCED_LIBRARIES_PATH, + NodeKind.CONTAINER, IClasspathEntry.CPE_CONTAINER); + private static final Gson gson = new GsonBuilder().registerTypeAdapterFactory(new CollectionTypeAdapterFactory()) .registerTypeAdapterFactory(new EnumTypeAdapterFactory()).create(); @@ -97,7 +104,6 @@ public static List getChildren(List arguments, IProgressMon throw new IllegalArgumentException("Should have at least one arugment for getChildren"); } PackageParams params = gson.fromJson(gson.toJson(arguments.get(0)), PackageParams.class); - BiFunction> loader = commands.get(params.getKind()); if (loader == null) { throw new CoreException(new Status(IStatus.ERROR, JdtlsExtActivator.PLUGIN_ID, String.format("Unknown classpath item type: %s", params.getKind()))); @@ -144,7 +150,13 @@ public static List resolvePath(List arguments, IProgressMon IPackageFragmentRoot pkgRoot = (IPackageFragmentRoot) packageFragment.getParent(); PackageNode rootNode = null; if (typeRoot instanceof IClassFile) { - rootNode = new PackageRootNode(pkgRoot.getElementName(), pkgRoot.getPath().toPortableString(), NodeKind.PACKAGEROOT, pkgRoot.getKind()); + IClasspathEntry entry = pkgRoot.getRawClasspathEntry(); + // Process Referenced Variable + if (entry.getEntryKind() == IClasspathEntry.CPE_VARIABLE) { + rootNode = getNodeFromClasspathVariable(entry); + } else { + rootNode = new PackageRootNode(pkgRoot.getElementName(), pkgRoot.getPath().toPortableString(), NodeKind.PACKAGEROOT, pkgRoot.getKind()); + } } else { rootNode = new PackageRootNode(ExtUtils.removeProjectSegment(typeRoot.getJavaProject().getElementName(), pkgRoot.getPath()).toPortableString(), pkgRoot.getPath().toPortableString(), NodeKind.PACKAGEROOT, pkgRoot.getKind()); @@ -154,8 +166,13 @@ public static List resolvePath(List arguments, IProgressMon if (typeRoot instanceof IClassFile) { IClasspathEntry entry = pkgRoot.getRawClasspathEntry(); IClasspathContainer container = JavaCore.getClasspathContainer(entry.getPath(), typeRoot.getJavaProject()); - PackageNode containerNode = new ContainerNode(container.getDescription(), container.getPath().toPortableString(), NodeKind.CONTAINER, - entry.getEntryKind()); + PackageNode containerNode = null; + if (entry.getEntryKind() == IClasspathEntry.CPE_LIBRARY || entry.getEntryKind() == IClasspathEntry.CPE_VARIABLE) { + containerNode = REFERENCED_LIBRARIES_CONTAINER; + } else { + containerNode = new ContainerNode(container.getDescription(), container.getPath().toPortableString(), NodeKind.CONTAINER, + entry.getEntryKind()); + } result.add(containerNode); } result.add(rootNode); @@ -174,28 +191,19 @@ public static List resolvePath(List arguments, IProgressMon */ private static List getContainers(PackageParams query, IProgressMonitor pm) { IJavaProject javaProject = getJavaProject(query.getProjectUri()); - if (javaProject != null) { try { IClasspathEntry[] references = javaProject.getRawClasspath(); - return Arrays.stream(references).map(entry -> { - try { - entry = JavaCore.getResolvedClasspathEntry(entry); - IClasspathContainer container = JavaCore.getClasspathContainer(entry.getPath(), javaProject); - // HACK: There is an initialization issue for the first container. - if (container == null) { - container = JavaCore.getClasspathContainer(entry.getPath(), javaProject); - } - - if (container != null) { - return new ContainerNode(container.getDescription(), container.getPath().toPortableString(), NodeKind.CONTAINER, - entry.getEntryKind()); - } - } catch (CoreException e) { - // Ignore it - } - return null; - }).filter(containerNode -> containerNode != null).collect(Collectors.toList()); + List result = Arrays.stream(references) + .filter(entry -> entry.getEntryKind() != IClasspathEntry.CPE_LIBRARY && entry.getEntryKind() != IClasspathEntry.CPE_VARIABLE) + .map(entry -> getNodeFromClasspathEntry(entry, javaProject, NodeKind.CONTAINER)).filter(containerNode -> containerNode != null) + .collect(Collectors.toList()); + boolean isReferencedLibrariesExist = Arrays.stream(references) + .anyMatch(entry -> entry.getEntryKind() == IClasspathEntry.CPE_LIBRARY || entry.getEntryKind() == IClasspathEntry.CPE_VARIABLE); + if (isReferencedLibrariesExist) { + result.add(REFERENCED_LIBRARIES_CONTAINER); + } + return result; } catch (CoreException e) { JdtlsExtActivator.logException("Problem load project library ", e); } @@ -203,7 +211,60 @@ private static List getContainers(PackageParams query, IProgressMon return Collections.emptyList(); } + /** + * Get the correspond node of classpath, it may be container or a package root + * + * @param classpathEntry + * classpath entry + * @param javaProject + * correspond java project + * @param nodeKind + * could be CONTAINER or PACKAGEROOT(for referenced libraries) + * @return correspond PackageNode of classpath entry + */ + private static PackageNode getNodeFromClasspathEntry(IClasspathEntry classpathEntry, IJavaProject javaProject, NodeKind nodeKind) { + try { + IClasspathEntry entry = JavaCore.getResolvedClasspathEntry(classpathEntry); + IClasspathContainer container = JavaCore.getClasspathContainer(entry.getPath(), javaProject); + // HACK: There is an initialization issue for the first container. + if (container == null) { + 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: + // 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; + } + } + } catch (CoreException e) { + JdtlsExtActivator.logException("Problems when convert classpath entry to package node ", e); + } + return null; + } + + /** + * Get correspond node of referenced variable + * + * @param classpathEntry + * referenced cariable's classpath entry + * @return correspond package node + */ + private static PackageNode getNodeFromClasspathVariable(IClasspathEntry classpathEntry) { + 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); + } + private static List getPackageFragmentRoots(PackageParams query, IProgressMonitor pm) { + ArrayList children = new ArrayList<>(); IJavaProject javaProject = getJavaProject(query.getProjectUri()); if (javaProject != null) { @@ -217,7 +278,6 @@ private static List getPackageFragmentRoots(PackageParams query, IP } } if (containerEntry != null) { - ArrayList children = new ArrayList<>(); IPackageFragmentRoot[] packageFragmentRoots = javaProject.findPackageFragmentRoots(containerEntry); for (IPackageFragmentRoot fragmentRoot : packageFragmentRoots) { String displayName = fragmentRoot.getElementName(); @@ -232,6 +292,16 @@ private static List getPackageFragmentRoots(PackageParams query, IP } } return children; + } else if (query.getPath().equals(REFERENCED_LIBRARIES_PATH)) { + // Process referenced libraries + List referLibs = Arrays.stream(references).filter(entry -> entry.getEntryKind() == IClasspathEntry.CPE_LIBRARY) + .map(classpath -> getNodeFromClasspathEntry(classpath, javaProject, NodeKind.PACKAGEROOT)).filter(entry -> entry != null) + .collect(Collectors.toList()); + List referVariables = Arrays.stream(references).filter(entry -> entry.getEntryKind() == IClasspathEntry.CPE_VARIABLE) + .map(classpath -> getNodeFromClasspathVariable(classpath)).filter(entry -> entry != null).collect(Collectors.toList()); + children.addAll(referLibs); + children.addAll(referVariables); + return children; } } catch (CoreException e) { JdtlsExtActivator.logException("Problem load project JAR entries ", e); @@ -243,9 +313,7 @@ private static List getPackageFragmentRoots(PackageParams query, IP private static List getPackages(PackageParams query, IProgressMonitor pm) { IJavaProject javaProject = getJavaProject(query.getProjectUri()); - if (javaProject != null) { - try { IPackageFragmentRoot packageRoot = javaProject.findPackageFragmentRoot(Path.fromPortableString(query.getRootPath())); if (packageRoot == null) { @@ -274,7 +342,7 @@ private static List getRootTypes(PackageParams query, IProgressMoni if (packageFragment != null) { IJavaElement[] types = packageFragment.getChildren(); Object[] nonJavaResources = packageFragment.getNonJavaResources(); - List rootTypeNodes = Arrays.stream(types).filter(typeRoot -> !typeRoot.getElementName().contains("$")).map(typeRoot -> { + List rootTypeNodes = 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) { @@ -289,20 +357,20 @@ private static List getRootTypes(PackageParams query, IProgressMoni } // when .java files and other .properties files are mixed up rootTypeNodes.addAll( - Arrays.stream(nonJavaResources).filter(resource -> resource instanceof IFile || resource instanceof JarEntryFile).map(resource -> { - if (resource instanceof IFile) { - IFile file = (IFile) resource; - PackageNode item = new PackageNode(file.getName(), file.getFullPath().toPortableString(), NodeKind.FILE); - item.setUri(JDTUtils.getFileURI(file)); - return item; - } else { - JarEntryFile file = (JarEntryFile) resource; - PackageNode entry = new PackageNode(file.getName(), file.getFullPath().toPortableString(), NodeKind.FILE); - entry.setUri(ExtUtils.toUri((JarEntryFile) resource)); - return entry; - } - - }).collect(Collectors.toList())); + Arrays.stream(nonJavaResources).filter(resource -> resource instanceof IFile || resource instanceof JarEntryFile).map(resource -> { + if (resource instanceof IFile) { + IFile file = (IFile) resource; + PackageNode item = new PackageNode(file.getName(), file.getFullPath().toPortableString(), NodeKind.FILE); + item.setUri(JDTUtils.getFileURI(file)); + return item; + } else { + JarEntryFile file = (JarEntryFile) resource; + PackageNode entry = new PackageNode(file.getName(), file.getFullPath().toPortableString(), NodeKind.FILE); + entry.setUri(ExtUtils.toUri((JarEntryFile) resource)); + return entry; + } + + }).collect(Collectors.toList())); return rootTypeNodes; } } catch (CoreException e) {