diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectResolver.kt b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectResolver.kt index 02eed85b3805..8206b1371d7e 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectResolver.kt +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectResolver.kt @@ -212,10 +212,12 @@ class MavenProjectResolver(private val myProject: Project) { val virtualFile = VirtualFileManager.getInstance().findFileByNioPath(file) ?: return@forEach val aggregatorProject = tree.findProject(virtualFile) ?: return@forEach modules.forEach modules@{ modulePath -> - val moduleFile = file.parent.resolve(modulePath).resolve("pom.xml") - val moduleVirtualFile = VirtualFileManager.getInstance().findFileByNioPath(moduleFile) ?: return@modules - val moduleProject = tree.findProject(moduleVirtualFile) ?: return@modules - tree.reconnect(aggregatorProject, moduleProject) + if (modulePath.isNotBlank()) { + val moduleFile = file.parent.resolve(modulePath).resolve("pom.xml") + val moduleVirtualFile = VirtualFileManager.getInstance().findFileByNioPath(moduleFile) ?: return@modules + val moduleProject = tree.findProject(moduleVirtualFile) ?: return@modules + tree.reconnect(aggregatorProject, moduleProject) + } } } diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsTree.kt b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsTree.kt index 5f0d364eac58..c8bfb7846603 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsTree.kt +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsTree.kt @@ -348,7 +348,7 @@ class MavenProjectsTree(val project: Project) { force: Boolean, generalSettings: MavenGeneralSettings, mavenEmbedderWrappers: MavenEmbedderWrappers, - process: MavenProgressIndicator + process: MavenProgressIndicator, ) { runBlockingMaybeCancellable { updateAll(force, generalSettings, mavenEmbedderWrappers, process.indicator) } } @@ -358,7 +358,7 @@ class MavenProjectsTree(val project: Project) { force: Boolean, generalSettings: MavenGeneralSettings, mavenEmbedderWrappers: MavenEmbedderWrappers, - process: ProgressIndicator + process: ProgressIndicator, ): MavenProjectsTreeUpdateResult { return updateAll(force, generalSettings, mavenEmbedderWrappers, toRawProgressReporter(process)) } @@ -400,11 +400,13 @@ class MavenProjectsTree(val project: Project) { return update(files, false, force, projectReader, progressReporter) } - private suspend fun update(files: Collection, - updateModules: Boolean, - forceRead: Boolean, - projectReader: MavenProjectReader, - progressReporter: RawProgressReporter): MavenProjectsTreeUpdateResult { + private suspend fun update( + files: Collection, + updateModules: Boolean, + forceRead: Boolean, + projectReader: MavenProjectReader, + progressReporter: RawProgressReporter, + ): MavenProjectsTreeUpdateResult { val updateContext = MavenProjectsTreeUpdateContext(this) val updater = MavenProjectsTreeUpdater( @@ -419,7 +421,7 @@ class MavenProjectsTree(val project: Project) { if (null == findProject(file)) { filesToAddModules.add(file) } - tracer.spanBuilder("updateProjectFile").useWithScope { updater.updateProjects(listOf(UpdateSpec(file, forceRead))) } + tracer.spanBuilder("updateProjectFile").useWithScope { updater.updateProjects(listOf(UpdateSpec(file, forceRead))) } } for (aggregator in projects) { @@ -490,9 +492,11 @@ class MavenProjectsTree(val project: Project) { return delete(projectReader, files, progressReporter) } - private suspend fun delete(projectReader: MavenProjectReader, - files: Collection, - progressReporter: RawProgressReporter): MavenProjectsTreeUpdateResult { + private suspend fun delete( + projectReader: MavenProjectReader, + files: Collection, + progressReporter: RawProgressReporter, + ): MavenProjectsTreeUpdateResult { val updateContext = MavenProjectsTreeUpdateContext(this) val inheritorsToUpdate: MutableSet = HashSet() @@ -583,7 +587,7 @@ class MavenProjectsTree(val project: Project) { val prevAggregator = findAggregator(project) if (prevAggregator === newAggregator) return false - + if (newAggregator === project) return false withWriteLock { if (prevAggregator != null) { removeModule(prevAggregator, project) @@ -780,11 +784,16 @@ class MavenProjectsTree(val project: Project) { private fun doFindRootProject(project: MavenProject): MavenProject { var rootProject = project + val traversed = LinkedHashSet().also { it.add(project) } while (true) { val aggregator = myModuleToAggregatorMapping[rootProject] if (aggregator == null) { return rootProject } + if (!traversed.add(aggregator)) { + MavenLog.LOG.warn("Recursive aggregator definition: ${traversed.joinToString(" -> ") { it.mavenId.toString() }}") + return project + } rootProject = aggregator } } @@ -941,9 +950,11 @@ class MavenProjectsTree(val project: Project) { fun profilesChanged() { } - fun projectsIgnoredStateChanged(ignored: List, - unignored: List, - fromImport: Boolean) { + fun projectsIgnoredStateChanged( + ignored: List, + unignored: List, + fromImport: Boolean, + ) { } fun projectsUpdated(updated: List>, deleted: List) { @@ -951,8 +962,10 @@ class MavenProjectsTree(val project: Project) { @Suppress("DEPRECATION") @Deprecated("use projectResolved(Pair)") - fun projectResolved(projectWithChanges: Pair, - nativeMavenProject: NativeMavenProjectHolder?) { + fun projectResolved( + projectWithChanges: Pair, + nativeMavenProject: NativeMavenProjectHolder?, + ) { } @Suppress("DEPRECATION") @@ -1152,8 +1165,10 @@ class MavenProjectsTree(val project: Project) { } @Throws(IOException::class) - private fun readProjectsRecursively(inputStream: DataInputStream, - tree: MavenProjectsTree): MutableList { + private fun readProjectsRecursively( + inputStream: DataInputStream, + tree: MavenProjectsTree, + ): MutableList { var count = inputStream.readInt() val result: MutableList = ArrayList(count) while (count-- > 0) { @@ -1176,9 +1191,11 @@ class MavenProjectsTree(val project: Project) { return result } - private fun updateExplicitProfiles(explicitProfiles: MutableCollection, - temporarilyRemovedExplicitProfiles: MutableCollection, - available: Set) { + private fun updateExplicitProfiles( + explicitProfiles: MutableCollection, + temporarilyRemovedExplicitProfiles: MutableCollection, + available: Set, + ) { val removedProfiles = HashSet(explicitProfiles) removedProfiles.removeAll(available) temporarilyRemovedExplicitProfiles.addAll(removedProfiles) diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/importing/InvalidProjectImportingTest.kt b/plugins/maven/src/test/java/org/jetbrains/idea/maven/importing/InvalidProjectImportingTest.kt index 76f0c45a2eb8..251f7d3033b7 100644 --- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/importing/InvalidProjectImportingTest.kt +++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/importing/InvalidProjectImportingTest.kt @@ -21,7 +21,6 @@ import com.intellij.build.events.BuildIssueEvent import com.intellij.build.events.MessageEvent import com.intellij.maven.testFramework.MavenMultiVersionImportingTestCase import com.intellij.openapi.application.edtWriteAction -import com.intellij.openapi.util.registry.Registry import com.intellij.testFramework.UsefulTestCase import com.intellij.testFramework.replaceService import kotlinx.coroutines.runBlocking @@ -1009,6 +1008,38 @@ class InvalidProjectImportingTest : MavenMultiVersionImportingTestCase() { assertProblems(root, "'settings.xml' has syntax errors") } + @Test + fun testImportingWithEmptyPath() = runBlocking { + importProjectAsync(""" + test + project + 1 + pom + + + + """.trimIndent()) + assertModules("project") + val rootProject = projectsManager.findProject(projectPom) + assertNotNull("Project should be found", rootProject) + val rootOfRoot = projectsManager.findRootProject(rootProject!!) + assertNotNull("Root of root should be null", rootOfRoot) + } + + @Test + fun testImportingWithSelfInclusionInclusion() = runBlocking { + importProjectAsync(""" + test + project + 1 + pom + + ./pom.xml + + """.trimIndent()) + assertModules("project") + } + private val rootProjects: List get() = projectsTree.rootProjects