diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenPluginResolver.kt b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenPluginResolver.kt index 1ababddd3808..337d7707c63f 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenPluginResolver.kt +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenPluginResolver.kt @@ -1,6 +1,7 @@ // Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package org.jetbrains.idea.maven.project +import com.intellij.openapi.progress.blockingContext import com.intellij.openapi.project.Project import com.intellij.openapi.util.Pair import com.intellij.openapi.util.registry.Registry @@ -18,11 +19,11 @@ class MavenPluginResolver(private val myTree: MavenProjectsTree) { private val myProject: Project = myTree.project @Throws(MavenProcessCanceledException::class) - fun resolvePlugins(mavenProjectsToResolvePlugins: Collection, - embeddersManager: MavenEmbeddersManager, - console: MavenConsole, - process: MavenProgressIndicator, - reportUnresolvedToSyncConsole: Boolean) { + suspend fun resolvePlugins(mavenProjectsToResolvePlugins: Collection, + embeddersManager: MavenEmbeddersManager, + console: MavenConsole, + process: MavenProgressIndicator, + reportUnresolvedToSyncConsole: Boolean) { val mavenProjects = mavenProjectsToResolvePlugins.filter { !it.mavenProject.hasReadingProblems() && it.mavenProject.hasUnresolvedPlugins() @@ -63,7 +64,9 @@ class MavenPluginResolver(private val myTree: MavenProjectsTree) { } finally { if (filesToRefresh.size > 0) { - LocalFileSystem.getInstance().refreshNioFiles(filesToRefresh) + blockingContext { + LocalFileSystem.getInstance().refreshNioFiles(filesToRefresh) + } } embeddersManager.release(embedder) } diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsManagerEx.kt b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsManagerEx.kt index 0ff25abc4718..af6615817827 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsManagerEx.kt +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsManagerEx.kt @@ -350,12 +350,8 @@ open class MavenProjectsManagerEx(project: Project) : MavenProjectsManager(proje val pluginResolver = MavenPluginResolver(projectsTree) withBackgroundProgress(myProject, MavenProjectBundle.message("maven.downloading.plugins"), true) { runMavenImportActivity(project, MavenProjectsProcessorPluginsResolvingTask::class.java) { - withRawProgressReporter { - coroutineToIndicator { - for (mavenProjects in resolutionResult.mavenProjectMap) { - pluginResolver.resolvePlugins(mavenProjects.value, embeddersManager, mavenConsole, indicator, true) - } - } + for (mavenProjects in resolutionResult.mavenProjectMap) { + pluginResolver.resolvePlugins(mavenProjects.value, embeddersManager, mavenConsole, indicator, true) } } } diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/importing/MavenImportFlow.kt b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/importing/MavenImportFlow.kt index 307ddcff3078..699fd52ded1b 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/importing/MavenImportFlow.kt +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/importing/MavenImportFlow.kt @@ -218,12 +218,14 @@ class MavenImportFlow { val consoleToBeRemoved = BTWMavenConsole(context.project, context.initialContext.generalSettings.outputLevel, context.initialContext.generalSettings.isPrintErrorStackTraces) - resolver.resolvePlugins( - context.projectsWithUnresolvedPlugins, - embeddersManager, - consoleToBeRemoved, - context.initialContext.indicator, - false) + runBlockingMaybeCancellable { + resolver.resolvePlugins( + context.projectsWithUnresolvedPlugins, + embeddersManager, + consoleToBeRemoved, + context.initialContext.indicator, + false) + } return MavenPluginResolvedContext(context.project, context) } diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/server/MavenEmbedderWrapper.kt b/plugins/maven/src/main/java/org/jetbrains/idea/maven/server/MavenEmbedderWrapper.kt index a514715e40fc..96adbbad2c06 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/server/MavenEmbedderWrapper.kt +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/server/MavenEmbedderWrapper.kt @@ -3,6 +3,7 @@ package org.jetbrains.idea.maven.server import com.intellij.openapi.progress.ProgressIndicator import com.intellij.openapi.progress.blockingContext +import com.intellij.openapi.progress.runBlockingMaybeCancellable import com.intellij.openapi.project.Project import com.intellij.openapi.util.Pair import com.intellij.openapi.vfs.VirtualFile @@ -123,9 +124,9 @@ abstract class MavenEmbedderWrapper internal constructor(private val project: Pr } @Throws(MavenProcessCanceledException::class) - fun resolvePlugins(mavenPluginRequests: Collection>, - progressIndicator: MavenProgressIndicator?, - console: MavenConsole?): List { + suspend fun resolvePlugins(mavenPluginRequests: Collection>, + progressIndicator: MavenProgressIndicator?, + console: MavenConsole?): List { val pluginResolutionRequests = ArrayList() for (mavenPluginRequest in mavenPluginRequests) { val mavenPluginId = mavenPluginRequest.first @@ -140,7 +141,7 @@ abstract class MavenEmbedderWrapper internal constructor(private val project: Pr } val indicator = progressIndicator?.indicator val syncConsole = progressIndicator?.syncConsole - return runLongRunningTask( + return runLongRunningTaskAsync( LongRunningEmbedderTask { embedder, taskId -> embedder.resolvePlugins(taskId, pluginResolutionRequests, ourToken) }, indicator, syncConsole, console) } @@ -148,8 +149,10 @@ abstract class MavenEmbedderWrapper internal constructor(private val project: Pr @Throws(MavenProcessCanceledException::class) fun resolvePlugin(plugin: MavenPlugin, nativeMavenProject: NativeMavenProjectHolder): Collection { val mavenId = plugin.mavenId - return resolvePlugins(listOf(Pair.create(mavenId, nativeMavenProject)), null, null) + return runBlockingMaybeCancellable { + resolvePlugins(listOf(Pair.create(mavenId, nativeMavenProject)), null, null) .flatMap { resolutionResult: PluginResolutionResponse -> resolutionResult.artifacts }.toSet() + } } @Throws(MavenProcessCanceledException::class) @@ -223,6 +226,17 @@ abstract class MavenEmbedderWrapper internal constructor(private val project: Pr return runLongRunningTask(embedder, longRunningTaskId, task, indicator, syncConsole, console) } + @Throws(MavenProcessCanceledException::class) + protected suspend fun runLongRunningTaskAsync(task: LongRunningEmbedderTask, + indicator: ProgressIndicator?, + syncConsole: MavenSyncConsole?, + console: MavenConsole?): R { + val longRunningTaskId = UUID.randomUUID().toString() + val embedder = getOrCreateWrappee() + + return runLongRunningTaskAsync(embedder, longRunningTaskId, indicator, syncConsole, console, task) + } + private fun runLongRunningTask(embedder: MavenServerEmbedder, longRunningTaskId: String, task: LongRunningEmbedderTask, diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/project/importing/MavenFolderResolverTestUtil.kt b/plugins/maven/src/test/java/org/jetbrains/idea/maven/project/importing/MavenFolderResolverTestUtil.kt deleted file mode 100644 index d65820ec9d65..000000000000 --- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/project/importing/MavenFolderResolverTestUtil.kt +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. -package org.jetbrains.idea.maven.project.importing - -import com.intellij.openapi.progress.runBlockingMaybeCancellable -import com.intellij.openapi.project.Project -import org.jetbrains.idea.maven.project.MavenFolderResolver -import org.jetbrains.idea.maven.project.MavenProject -import org.jetbrains.idea.maven.project.MavenProjectChanges - -internal fun resolveFoldersSync(project: Project, mavenProjects: Collection) : Map { - return runBlockingMaybeCancellable { - return@runBlockingMaybeCancellable MavenFolderResolver(project).resolveFolders(mavenProjects) - } -} \ No newline at end of file diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/project/importing/MavenProjectsTreeReadingPluginTest.kt b/plugins/maven/src/test/java/org/jetbrains/idea/maven/project/importing/MavenProjectsTreeReadingPluginTest.kt new file mode 100644 index 000000000000..fada79fa45a3 --- /dev/null +++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/project/importing/MavenProjectsTreeReadingPluginTest.kt @@ -0,0 +1,79 @@ +// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +package org.jetbrains.idea.maven.project.importing + +import com.intellij.openapi.util.Pair +import kotlinx.coroutines.runBlocking +import org.jetbrains.idea.maven.project.* +import org.jetbrains.idea.maven.server.NativeMavenProjectHolder +import org.junit.Test + +class MavenProjectsTreeReadingPluginTest : MavenProjectsTreeTestCase() { + @Test + @Throws(Exception::class) + fun testDoNotUpdateChildAfterParentWasResolved() { + createProjectPom(""" + test + parent + 1 + """.trimIndent()) + val child = createModulePom("child", + """ + test + child + 1 + + test + parent + 1 + + """.trimIndent()) + val listener = MyLoggingListener() + myTree.addListener(listener, getTestRootDisposable()) + updateAll(myProjectPom, child) + val parentProject = myTree.findProject(myProjectPom)!! + val embeddersManager = MavenEmbeddersManager(myProject) + try { + val nativeProject = arrayOfNulls(1) + myTree.addListener(object : MavenProjectsTree.Listener { + override fun projectResolved(projectWithChanges: Pair, + nativeMavenProject: NativeMavenProjectHolder?) { + nativeProject[0] = nativeMavenProject + } + }, getTestRootDisposable()) + resolve(myProject, + parentProject, + mavenGeneralSettings, + embeddersManager, + NULL_MAVEN_CONSOLE, + mavenProgressIndicator + ) + val pluginResolver = MavenPluginResolver(myTree) + runBlocking { + pluginResolver.resolvePlugins(listOf(MavenProjectWithHolder(parentProject, nativeProject[0]!!, MavenProjectChanges.ALL)), + embeddersManager, + NULL_MAVEN_CONSOLE, + mavenProgressIndicator, + false) + MavenFolderResolver(myProject).resolveFolders(listOf(parentProject)) + } + } + finally { + embeddersManager.releaseInTests() + } + assertEquals( + log() + .add("updated", "parent", "child") + .add("deleted") + .add("resolved", "parent") + .add("folders", "parent"), + listener.log) + myTree.updateAll(false, mavenGeneralSettings, mavenProgressIndicator.indicator) + assertEquals( + log() + .add("updated", "parent", "child") + .add("deleted") + .add("resolved", "parent") + .add("folders", "parent"), + listener.log) + } +} \ No newline at end of file diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/project/importing/MavenProjectsTreeReadingTest.java b/plugins/maven/src/test/java/org/jetbrains/idea/maven/project/importing/MavenProjectsTreeReadingTest.java index eb5cca6becc1..7ebb5d3aea93 100644 --- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/project/importing/MavenProjectsTreeReadingTest.java +++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/project/importing/MavenProjectsTreeReadingTest.java @@ -735,81 +735,6 @@ public class MavenProjectsTreeReadingTest extends MavenProjectsTreeTestCase { assertNull(nativeProject.get(0)); } - @Test - public void testDoNotUpdateChildAfterParentWasResolved() throws Exception { - createProjectPom(""" - test - parent - 1 - """); - - VirtualFile child = createModulePom("child", - """ - test - child - 1 - - test - parent - 1 - - """); - - MyLoggingListener listener = new MyLoggingListener(); - myTree.addListener(listener, getTestRootDisposable()); - - updateAll(myProjectPom, child); - - MavenProject parentProject = myTree.findProject(myProjectPom); - - MavenEmbeddersManager embeddersManager = new MavenEmbeddersManager(myProject); - try { - final NativeMavenProjectHolder[] nativeProject = new NativeMavenProjectHolder[1]; - myTree.addListener(new MavenProjectsTree.Listener() { - @Override - public void projectResolved(@NotNull Pair projectWithChanges, - NativeMavenProjectHolder nativeMavenProject) { - nativeProject[0] = nativeMavenProject; - } - }, getTestRootDisposable()); - resolve(myProject, - parentProject, - getMavenGeneralSettings(), - embeddersManager, - NULL_MAVEN_CONSOLE, - getMavenProgressIndicator() - ); - - var pluginResolver = new MavenPluginResolver(myTree); - pluginResolver.resolvePlugins(List.of(new MavenProjectWithHolder(parentProject, nativeProject[0], MavenProjectChanges.ALL)), - embeddersManager, - NULL_MAVEN_CONSOLE, - getMavenProgressIndicator(), - false); - - MavenFolderResolverTestUtilKt.resolveFoldersSync(myProject, List.of(parentProject)); - } - finally { - embeddersManager.releaseInTests(); - } - - assertEquals( - log() - .add("updated", "parent", "child") - .add("deleted") - .add("resolved", "parent") - .add("folders", "parent"), - listener.log); - myTree.updateAll(false, getMavenGeneralSettings(), getMavenProgressIndicator().getIndicator()); - assertEquals( - log() - .add("updated", "parent", "child") - .add("deleted") - .add("resolved", "parent") - .add("folders", "parent"), - listener.log); - } - @Test public void testAddingInheritanceParent() { VirtualFile child = createModulePom("child", @@ -2577,64 +2502,4 @@ public class MavenProjectsTreeReadingTest extends MavenProjectsTreeTestCase { PlatformTestUtil.assertPathsEqual(pathFromBasedir("my-target/classes"), project.getOutputDirectory()); PlatformTestUtil.assertPathsEqual(pathFromBasedir("my-target/test-classes"), project.getTestOutputDirectory()); } - - private void resolve(@NotNull Project project, - @NotNull MavenProject mavenProject, - @NotNull MavenGeneralSettings generalSettings, - @NotNull MavenEmbeddersManager embeddersManager, - @NotNull MavenConsole console, - @NotNull MavenProgressIndicator process) throws MavenProcessCanceledException { - var resolver = MavenProjectResolver.getInstance(project); - resolver.resolve(List.of(mavenProject), myTree, generalSettings, embeddersManager, console, process.getIndicator(), process.getSyncConsole()); - } - - private static ListenerLog log() { - return new ListenerLog(); - } - - private static class ListenerLog extends CopyOnWriteArrayList>> { - ListenerLog() { super(); } - - ListenerLog(ListenerLog log) { super(log); } - - ListenerLog add(String key, String... values) { - var log = new ListenerLog(this); - log.add(new Pair<>(key, Set.of(values))); - return log; - } - } - - private static class MyLoggingListener implements MavenProjectsTree.Listener { - List>> log = new CopyOnWriteArrayList<>(); - - private void add(String key, Set value) { - log.add(new Pair<>(key, value)); - } - - @Override - public void projectsUpdated(@NotNull List> updated, @NotNull List deleted) { - append(MavenUtil.collectFirsts(updated), "updated"); - append(deleted, "deleted"); - } - - private void append(List updated, String text) { - add(text, updated.stream().map(each -> each.getMavenId().getArtifactId()).collect(Collectors.toSet())); - } - - @Override - public void projectResolved(@NotNull Pair projectWithChanges, - NativeMavenProjectHolder nativeMavenProject) { - add("resolved", Set.of(projectWithChanges.first.getMavenId().getArtifactId())); - } - - @Override - public void pluginsResolved(@NotNull MavenProject project) { - add("plugins", Set.of(project.getMavenId().getArtifactId())); - } - - @Override - public void foldersResolved(@NotNull Pair projectWithChanges) { - add("folders", Set.of(projectWithChanges.first.getMavenId().getArtifactId())); - } - } } diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/project/importing/MavenProjectsTreeTestCase.java b/plugins/maven/src/test/java/org/jetbrains/idea/maven/project/importing/MavenProjectsTreeTestCase.java index 11eb3e974f76..ae8781c6da84 100644 --- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/project/importing/MavenProjectsTreeTestCase.java +++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/project/importing/MavenProjectsTreeTestCase.java @@ -17,14 +17,23 @@ package org.jetbrains.idea.maven.project.importing; import com.intellij.maven.testFramework.MavenMultiVersionImportingTestCase; import com.intellij.openapi.application.WriteAction; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Pair; import com.intellij.openapi.vfs.VirtualFile; +import org.jetbrains.annotations.NotNull; import org.jetbrains.idea.maven.model.MavenExplicitProfiles; -import org.jetbrains.idea.maven.project.MavenProjectsManager; -import org.jetbrains.idea.maven.project.MavenProjectsTree; +import org.jetbrains.idea.maven.project.*; +import org.jetbrains.idea.maven.server.NativeMavenProjectHolder; +import org.jetbrains.idea.maven.utils.MavenProcessCanceledException; +import org.jetbrains.idea.maven.utils.MavenProgressIndicator; +import org.jetbrains.idea.maven.utils.MavenUtil; import java.io.IOException; import java.util.Collections; import java.util.List; +import java.util.Set; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.stream.Collectors; import static java.util.Arrays.asList; @@ -62,4 +71,70 @@ public abstract class MavenProjectsTreeTestCase extends MavenMultiVersionImporti } }); } + + protected static ListenerLog log() { + return new ListenerLog(); + } + + protected static class ListenerLog extends CopyOnWriteArrayList>> { + ListenerLog() { super(); } + + ListenerLog(ListenerLog log) { super(log); } + + ListenerLog add(String key, String... values) { + var log = new ListenerLog(this); + log.add(new Pair<>(key, Set.of(values))); + return log; + } + } + + protected static class MyLoggingListener implements MavenProjectsTree.Listener { + List>> log = new CopyOnWriteArrayList<>(); + + private void add(String key, Set value) { + log.add(new Pair<>(key, value)); + } + + @Override + public void projectsUpdated(@NotNull List> updated, @NotNull List deleted) { + append(MavenUtil.collectFirsts(updated), "updated"); + append(deleted, "deleted"); + } + + private void append(List updated, String text) { + add(text, updated.stream().map(each -> each.getMavenId().getArtifactId()).collect(Collectors.toSet())); + } + + @Override + public void projectResolved(@NotNull Pair projectWithChanges, + NativeMavenProjectHolder nativeMavenProject) { + add("resolved", Set.of(projectWithChanges.first.getMavenId().getArtifactId())); + } + + @Override + public void pluginsResolved(@NotNull MavenProject project) { + add("plugins", Set.of(project.getMavenId().getArtifactId())); + } + + @Override + public void foldersResolved(@NotNull Pair projectWithChanges) { + add("folders", Set.of(projectWithChanges.first.getMavenId().getArtifactId())); + } + } + + protected void resolve(@NotNull Project project, + @NotNull MavenProject mavenProject, + @NotNull MavenGeneralSettings generalSettings, + @NotNull MavenEmbeddersManager embeddersManager, + @NotNull MavenConsole console, + @NotNull MavenProgressIndicator process) throws MavenProcessCanceledException { + var resolver = MavenProjectResolver.getInstance(project); + resolver.resolve(List.of(mavenProject), + myTree, + generalSettings, + embeddersManager, + console, + process.getIndicator(), + process.getSyncConsole()); + } }