diff --git a/CHANGELOG.md b/CHANGELOG.md index b9416af7..5a0960b5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Display non-Java files in Java Projects explorer. [#145](https://github.com/microsoft/vscode-java-dependency/issues/145) - Apply file decorators to project level. [#481](https://github.com/microsoft/vscode-java-dependency/issues/481) - Give more hints about the project import status. [#580](https://github.com/microsoft/vscode-java-dependency/issues/580) - +- Show non Java Projects in the Java Projects explorer. [#736](https://github.com/microsoft/vscode-java-dependency/issues/736) ### Fixed - Apply `files.exclude` to Java Projects explorer. [#214](https://github.com/microsoft/vscode-java-dependency/issues/214) diff --git a/extension.bundle.ts b/extension.bundle.ts index e192e8ff..e07cf41e 100644 --- a/extension.bundle.ts +++ b/extension.bundle.ts @@ -28,3 +28,6 @@ export { languageServerApiManager } from "./src/languageServerApi/languageServer // tasks export { BuildTaskProvider, categorizePaths, getFinalPaths } from "./src/tasks/build/buildTaskProvider"; + +// delegate commands +export { Jdtls } from "./src/java/jdtls"; 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 f91eb429..e58af4d4 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 @@ -19,6 +19,7 @@ import java.util.LinkedList; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.function.BiFunction; import java.util.stream.Collectors; @@ -31,6 +32,7 @@ import org.eclipse.core.resources.IWorkspaceRoot; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.OperationCanceledException; @@ -257,18 +259,22 @@ private static List getParentAncestorNodes(IResource element) throw * Get the class path container list. */ private static List getProjectChildren(PackageParams query, IProgressMonitor pm) { - IJavaProject javaProject = getJavaProject(query.getProjectUri()); - if (javaProject != null) { - refreshLocal(javaProject.getProject(), pm); - List children = new LinkedList<>(); - boolean hasReferencedLibraries = false; - try { + IProject project = getProject(query.getProjectUri()); + if (project == null) { + JdtlsExtActivator.logError("Failed to find project at: " + query.getProjectUri()); + } + + List children = new LinkedList<>(); + boolean hasReferencedLibraries = false; + IJavaProject javaProject = JavaCore.create(project); + try { + if (ProjectUtils.isJavaProject(project) && javaProject != null) { + refreshLocal(javaProject.getProject(), pm); IClasspathEntry[] references = javaProject.getRawClasspath(); for (IClasspathEntry entry : references) { int entryKind = entry.getEntryKind(); if (entryKind == IClasspathEntry.CPE_SOURCE) { - IPackageFragmentRoot[] packageFragmentRoots = javaProject.findPackageFragmentRoots(entry); - children.addAll(Arrays.asList(packageFragmentRoots)); + Collections.addAll(children, javaProject.findPackageFragmentRoots(entry)); } else if (entryKind == IClasspathEntry.CPE_CONTAINER) { children.add(entry); } else if (entry.getEntryKind() == IClasspathEntry.CPE_LIBRARY || entry.getEntryKind() == IClasspathEntry.CPE_VARIABLE) { @@ -278,24 +284,32 @@ private static List getProjectChildren(PackageParams query, IProgre } } Collections.addAll(children, javaProject.getNonJavaResources()); - } catch (CoreException e) { - JdtlsExtActivator.logException("Problem load project library ", e); + } else { + Set projectPaths = Arrays.stream(ProjectUtils.getAllProjects()) + .map(IProject::getLocation).collect(Collectors.toSet()); + IResource[] members = project.members(); + for (IResource member : members) { + if (!projectPaths.contains(member.getLocation())) { + children.add(member); + } + } } + } catch (CoreException e) { + JdtlsExtActivator.logException("Problem load project library ", e); + } - ResourceSet resourceSet = new ResourceSet(children); - ResourceVisitor visitor = new JavaResourceVisitor(javaProject); - resourceSet.accept(visitor); - List result = visitor.getNodes(); + ResourceSet resourceSet = new ResourceSet(children); + ResourceVisitor visitor = new JavaResourceVisitor(javaProject); + resourceSet.accept(visitor); + List result = visitor.getNodes(); - // Invisible project will always have the referenced libraries entry - if (!ProjectUtils.isVisibleProject(javaProject.getProject())) { - result.add(PackageNode.REFERENCED_LIBRARIES_CONTAINER); - } else if (hasReferencedLibraries) { - result.add(PackageNode.IMMUTABLE_REFERENCED_LIBRARIES_CONTAINER); - } - return result; + // Invisible project will always have the referenced libraries entry + if (!ProjectUtils.isVisibleProject(project)) { + result.add(PackageNode.REFERENCED_LIBRARIES_CONTAINER); + } else if (hasReferencedLibraries) { + result.add(PackageNode.IMMUTABLE_REFERENCED_LIBRARIES_CONTAINER); } - return Collections.emptyList(); + return result; } private static List getContainerChildren(PackageParams query, IProgressMonitor pm) { @@ -567,7 +581,7 @@ private static Object[] findJarDirectoryChildren(JarEntryDirectory directory, St return null; } - public static IJavaProject getJavaProject(String projectUri) { + public static IProject getProject(String projectUri) { IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot(); IContainer[] containers = root.findContainersForLocationURI(JDTUtils.toURI(projectUri)); @@ -576,8 +590,7 @@ public static IJavaProject getJavaProject(String projectUri) { } // For multi-module scenario, findContainersForLocationURI API may return a container array, - // need filter out non-Java project and put the result from the nearest project in front. - containers = Arrays.stream(containers).filter(c -> ProjectUtils.isJavaProject(c.getProject())).toArray(IContainer[]::new); + // put the result from the nearest project in front. Arrays.sort(containers, (Comparator) (IContainer a, IContainer b) -> { return a.getFullPath().toPortableString().length() - b.getFullPath().toPortableString().length(); }); @@ -587,11 +600,16 @@ public static IJavaProject getJavaProject(String projectUri) { if (!project.exists()) { return null; } - return JavaCore.create(project); + return project; } return null; } + public static IJavaProject getJavaProject(String projectUri) { + IProject project = getProject(projectUri); + return JavaCore.create(project); + } + private static void refreshLocal(IResource resource, IProgressMonitor monitor) { if (resource == null || !resource.exists()) { return; diff --git a/jdtls.ext/com.microsoft.jdtls.ext.core/src/com/microsoft/jdtls/ext/core/ProjectCommand.java b/jdtls.ext/com.microsoft.jdtls.ext.core/src/com/microsoft/jdtls/ext/core/ProjectCommand.java index 968a1af4..bb708f28 100644 --- a/jdtls.ext/com.microsoft.jdtls.ext.core/src/com/microsoft/jdtls/ext/core/ProjectCommand.java +++ b/jdtls.ext/com.microsoft.jdtls.ext.core/src/com/microsoft/jdtls/ext/core/ProjectCommand.java @@ -18,6 +18,7 @@ import java.io.FileOutputStream; import java.io.IOException; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Objects; @@ -98,10 +99,20 @@ public static List listProjects(List arguments, IProgressMo String workspaceUri = (String) arguments.get(0); IPath workspaceFolderPath = ResourceUtils.canonicalFilePathFromURI(workspaceUri); - IJavaProject[] javaProjects = ProjectUtils.getJavaProjects(); + IProject[] projects; + boolean includeNonJava = false; + if (arguments.size() > 1) { + includeNonJava = (boolean) arguments.get(1); + } + if (includeNonJava) { + projects = ProjectUtils.getAllProjects(); + } else { + projects = Arrays.stream(ProjectUtils.getJavaProjects()) + .map(IJavaProject::getProject).toArray(IProject[]::new); + } + ArrayList children = new ArrayList<>(); - for (IJavaProject javaProject : javaProjects) { - IProject project = javaProject.getProject(); + for (IProject project : projects) { if (!project.isAccessible() || project.getLocation() == null) { continue; } diff --git a/src/java/jdtls.ts b/src/java/jdtls.ts index bdd9a498..ad7c228b 100644 --- a/src/java/jdtls.ts +++ b/src/java/jdtls.ts @@ -11,7 +11,12 @@ import { INodeData } from "./nodeData"; export namespace Jdtls { export async function getProjects(params: string): Promise { - return await commands.executeCommand(Commands.EXECUTE_WORKSPACE_COMMAND, Commands.JAVA_PROJECT_LIST, params) || []; + return await commands.executeCommand( + Commands.EXECUTE_WORKSPACE_COMMAND, + Commands.JAVA_PROJECT_LIST, + params, + true /*includeNonJavaProjects*/ + ) || []; } export async function getProjectUris(): Promise { diff --git a/test/maven-suite/projectView.test.ts b/test/maven-suite/projectView.test.ts index 11fffebf..03a4fe6e 100644 --- a/test/maven-suite/projectView.test.ts +++ b/test/maven-suite/projectView.test.ts @@ -5,8 +5,8 @@ import * as assert from "assert"; import * as clipboardy from "clipboardy"; import * as path from "path"; import * as vscode from "vscode"; -import { Commands, ContainerNode, contextManager, DataNode, DependencyExplorer, FileNode, IMainClassInfo, - INodeData, NodeKind, PackageNode, PackageRootNode, PrimaryTypeNode, ProjectNode } from "../../extension.bundle"; +import { Commands, ContainerNode, contextManager, DataNode, DependencyExplorer, FileNode, + INodeData, Jdtls, NodeKind, PackageNode, PackageRootNode, PrimaryTypeNode, ProjectNode } from "../../extension.bundle"; import { fsPath, setupTestEnv, Uris } from "../shared"; import { sleep } from "../util"; @@ -175,8 +175,7 @@ suite("Maven Project View Tests", () => { test("Can execute command java.project.list correctly", async function() { const workspaceFolders = vscode.workspace.workspaceFolders; assert.ok(workspaceFolders, `There should be valid workspace folders`); - const projects = await vscode.commands.executeCommand(Commands.EXECUTE_WORKSPACE_COMMAND, - Commands.JAVA_PROJECT_LIST, workspaceFolders![0].uri.toString()); + const projects = await Jdtls.getProjects(workspaceFolders![0].uri.toString()); assert.equal(projects?.length, 1, "project's length should be 1"); assert.equal(projects![0].name, "my-app", "project should be my-app"); }); @@ -217,8 +216,7 @@ suite("Maven Project View Tests", () => { test("Can execute command java.project.getMainClasses correctly", async function() { const workspaceFolders = vscode.workspace.workspaceFolders; assert.ok(workspaceFolders, `There should be valid workspace folders`); - const mainClasses = await vscode.commands.executeCommand(Commands.EXECUTE_WORKSPACE_COMMAND, - Commands.JAVA_PROJECT_GETMAINCLASSES, workspaceFolders![0].uri.toString()); + const mainClasses = await Jdtls.getMainClasses(workspaceFolders![0].uri.toString()); assert.equal(mainClasses?.length, 1, "mainClasses' length should be 1"); assert.equal(mainClasses![0].name, "com.mycompany.app.App", "mainClasses[0]'s name should be com.mycompany.app.App"); });