diff --git a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/AbstractProjectImporter.java b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/AbstractProjectImporter.java index f5f15f61a0..0721ab174e 100644 --- a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/AbstractProjectImporter.java +++ b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/AbstractProjectImporter.java @@ -45,8 +45,20 @@ public void initialize(File rootFolder) { public abstract boolean applies(IProgressMonitor monitor) throws OperationCanceledException, CoreException; @Override - public boolean isResolved(File folder) throws OperationCanceledException, CoreException { - return directories != null && directories.contains(folder.toPath()); + public boolean isResolved(File file) throws OperationCanceledException, CoreException { + if (directories == null) { + return false; + } + // if input is a directory (usually the root folder), + // check if the importer has imported it. + if (file.isDirectory()) { + return directories.contains(file.toPath()); + } + + // if the input is a file, check if the parent directory is imported. + return directories.stream().anyMatch((directory) -> { + return file.toPath().getParent().equals(directory); + }); }; @Override @@ -82,6 +94,10 @@ protected Collection findProjectPathByConfigurationName(Collection return filteredPaths; } + return eliminateNestedPaths(filteredPaths); + } + + protected List eliminateNestedPaths(List filteredPaths) { Path parentDir = null; List result = new LinkedList<>(); for (Path path : filteredPaths) { @@ -95,7 +111,6 @@ protected Collection findProjectPathByConfigurationName(Collection parentDir = path; } } - return result; } } diff --git a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/managers/GradleProjectImporter.java b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/managers/GradleProjectImporter.java index 8def245767..ab094dbcdc 100644 --- a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/managers/GradleProjectImporter.java +++ b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/managers/GradleProjectImporter.java @@ -127,6 +127,11 @@ public class GradleProjectImporter extends AbstractProjectImporter { .replaceAll("\n", System.lineSeparator()); //@formatter:on + /** + * A flag whether this importer is activated by manual selection mode. + */ + private boolean manualSelection = false; + /* (non-Javadoc) * @see org.eclipse.jdt.ls.core.internal.managers.IProjectImporter#applies(org.eclipse.core.runtime.IProgressMonitor) */ @@ -158,6 +163,7 @@ public boolean applies(IProgressMonitor monitor) throws CoreException { @Override public boolean applies(Collection buildFiles, IProgressMonitor monitor) { + manualSelection = true; if (!getPreferences().isImportGradleEnabled()) { return false; } @@ -167,7 +173,7 @@ public boolean applies(Collection buildFiles, IProgressMonitor monitor) { SETTINGS_GRADLE_DESCRIPTOR, BUILD_GRADLE_KTS_DESCRIPTOR, SETTINGS_GRADLE_KTS_DESCRIPTOR - ), false /*includeNested*/); + ), true /*includeNested*/); if (configurationDirs == null || configurationDirs.isEmpty()) { return false; } @@ -199,16 +205,20 @@ public void importToWorkspace(IProgressMonitor monitor) throws CoreException { if (!applies(monitor)) { return; } - int projectSize = directories.size(); + List directoriesToImport = new ArrayList<>(this.directories); + if (manualSelection) { + directoriesToImport = eliminateNestedPaths(directoriesToImport); + } + int projectSize = directoriesToImport.size(); SubMonitor subMonitor = SubMonitor.convert(monitor, projectSize + 1); subMonitor.setTaskName(IMPORTING_GRADLE_PROJECTS); JavaLanguageServerPlugin.logInfo(IMPORTING_GRADLE_PROJECTS); subMonitor.worked(1); // run just once at the first project, assuming that all projects are using the same gradle version. - inferGradleJavaHome(directories.iterator().next(), monitor); + inferGradleJavaHome(directoriesToImport.iterator().next(), monitor); MultiStatus compatibilityStatus = new MultiStatus(IConstants.PLUGIN_ID, -1, "Compatibility issue occurs when importing Gradle projects", null); MultiStatus gradleUpgradeWrapperStatus = new MultiStatus(IConstants.PLUGIN_ID, -1, "Gradle upgrade wrapper", null); - for (Path directory : directories) { + for (Path directory : directoriesToImport) { IStatus importStatus = importDir(directory, subMonitor.newChild(1)); if (isFailedStatus(importStatus) && importStatus instanceof GradleCompatibilityStatus) { compatibilityStatus.add(importStatus); diff --git a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/managers/ProjectsManager.java b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/managers/ProjectsManager.java index e04e83f4f6..43921f9a60 100644 --- a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/managers/ProjectsManager.java +++ b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/managers/ProjectsManager.java @@ -23,10 +23,11 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Map.Entry; import java.util.Objects; import java.util.Optional; +import java.util.Set; import java.util.TreeMap; -import java.util.Map.Entry; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -173,11 +174,14 @@ protected void importProjectsFromConfigurationFiles(Collection rootPaths, MultiStatus importStatusCollection = new MultiStatus(IConstants.PLUGIN_ID, -1, "Failed to import projects", null); for (IPath rootPath : rootPaths) { File rootFolder = rootPath.toFile(); + Set buildFiles = projectConfigurations.stream() + .filter(rootPath::isPrefixOf).collect(Collectors.toSet()); try { for (IProjectImporter importer : importers()) { importer.initialize(rootFolder); - if (importer.applies(projectConfigurations, subMonitor.split(1))) { + if (importer.applies(buildFiles, subMonitor.split(1))) { importer.importToWorkspace(subMonitor.split(70)); + buildFiles = removeImportedConfigurations(buildFiles, importer); } } } catch (CoreException e) { @@ -191,6 +195,18 @@ protected void importProjectsFromConfigurationFiles(Collection rootPaths, } } + private Set removeImportedConfigurations(Set configurations, IProjectImporter importer) { + return configurations.stream() + .filter(config -> { + try { + return !importer.isResolved(config.toFile()); + } catch (OperationCanceledException | CoreException e) { + return true; + } + }) + .collect(Collectors.toSet()); + } + public void importProjects(IProgressMonitor monitor) { WorkspaceJob job = new WorkspaceJob("Importing projects in workspace...") { diff --git a/org.eclipse.jdt.ls.tests/src/org/eclipse/jdt/ls/core/internal/managers/ProjectsManagerTest.java b/org.eclipse.jdt.ls.tests/src/org/eclipse/jdt/ls/core/internal/managers/ProjectsManagerTest.java index 795c510f56..24a90ec863 100644 --- a/org.eclipse.jdt.ls.tests/src/org/eclipse/jdt/ls/core/internal/managers/ProjectsManagerTest.java +++ b/org.eclipse.jdt.ls.tests/src/org/eclipse/jdt/ls/core/internal/managers/ProjectsManagerTest.java @@ -231,13 +231,14 @@ public void dontFilterGitLikePackages() throws Exception { @Test public void testImportMavenSubModule() throws IOException, OperationCanceledException, CoreException { - Path projectDir = copyFiles("maven/multimodule", true).toPath(); + File projectDir = copyFiles("maven/multimodule", true); + Path projectDirPath = projectDir.toPath(); Collection configurationPaths = new ArrayList<>(); - Path subModuleConfiguration = projectDir.resolve("module1/pom.xml"); + Path subModuleConfiguration = projectDirPath.resolve("module1/pom.xml"); IPath filePath = ResourceUtils.canonicalFilePathFromURI(subModuleConfiguration.toUri().toString()); configurationPaths.add(filePath); preferenceManager.getPreferences().setProjectConfigurations(configurationPaths); - projectsManager.initializeProjects(Collections.singleton(new org.eclipse.core.runtime.Path(projectDir.toString())), monitor); + projectsManager.initializeProjects(Collections.singleton(new org.eclipse.core.runtime.Path(projectDir.getAbsolutePath())), monitor); IProject[] allProjects = ProjectUtils.getAllProjects(); Set expectedProjects = new HashSet<>(Arrays.asList( "module1", @@ -252,13 +253,14 @@ public void testImportMavenSubModule() throws IOException, OperationCanceledExce @Test public void testImportMixedProjects() throws IOException, OperationCanceledException, CoreException { - Path projectDir = copyFiles("mixed", true).toPath(); + File projectDir = copyFiles("mixed", true); + Path projectDirPath = projectDir.toPath(); Collection configurationPaths = new ArrayList<>(); - configurationPaths.add(ResourceUtils.canonicalFilePathFromURI(projectDir.resolve("hello/.project").toUri().toString())); - configurationPaths.add(ResourceUtils.canonicalFilePathFromURI(projectDir.resolve("simple-gradle/build.gradle").toUri().toString())); - configurationPaths.add(ResourceUtils.canonicalFilePathFromURI(projectDir.resolve("salut/pom.xml").toUri().toString())); + configurationPaths.add(ResourceUtils.canonicalFilePathFromURI(projectDirPath.resolve("hello/.project").toUri().toString())); + configurationPaths.add(ResourceUtils.canonicalFilePathFromURI(projectDirPath.resolve("simple-gradle/build.gradle").toUri().toString())); + configurationPaths.add(ResourceUtils.canonicalFilePathFromURI(projectDirPath.resolve("salut/pom.xml").toUri().toString())); preferenceManager.getPreferences().setProjectConfigurations(configurationPaths); - projectsManager.initializeProjects(Collections.singleton(new org.eclipse.core.runtime.Path(projectDir.toString())), monitor); + projectsManager.initializeProjects(Collections.singleton(new org.eclipse.core.runtime.Path(projectDir.getAbsolutePath())), monitor); IProject[] allProjects = ProjectUtils.getAllProjects(); Set expectedProjects = new HashSet<>(Arrays.asList( "jdt.ls-java-project", @@ -274,12 +276,13 @@ public void testImportMixedProjects() throws IOException, OperationCanceledExcep @Test public void testImportMixedProjectsPartially() throws IOException, OperationCanceledException, CoreException { - Path projectDir = copyFiles("mixed", true).toPath(); + File projectDir = copyFiles("mixed", true); + Path projectDirPath = projectDir.toPath(); Collection configurationPaths = new ArrayList<>(); - configurationPaths.add(ResourceUtils.canonicalFilePathFromURI(projectDir.resolve("simple-gradle/build.gradle").toUri().toString())); - configurationPaths.add(ResourceUtils.canonicalFilePathFromURI(projectDir.resolve("salut/pom.xml").toUri().toString())); + configurationPaths.add(ResourceUtils.canonicalFilePathFromURI(projectDirPath.resolve("simple-gradle/build.gradle").toUri().toString())); + configurationPaths.add(ResourceUtils.canonicalFilePathFromURI(projectDirPath.resolve("salut/pom.xml").toUri().toString())); preferenceManager.getPreferences().setProjectConfigurations(configurationPaths); - projectsManager.initializeProjects(Collections.singleton(new org.eclipse.core.runtime.Path(projectDir.toString())), monitor); + projectsManager.initializeProjects(Collections.singleton(new org.eclipse.core.runtime.Path(projectDir.getAbsolutePath())), monitor); IProject[] allProjects = ProjectUtils.getAllProjects(); Set expectedProjects = new HashSet<>(Arrays.asList( "jdt.ls-java-project",