[maven] GTW-5441 suspend fun resolvePlugins

GitOrigin-RevId: b8959f7a0c0758ab661a9379ceb8215bc502d925
This commit is contained in:
Dmitry Kichinsky
2023-07-18 07:11:28 +00:00
committed by intellij-monorepo-bot
parent 5f0fe24b45
commit 07a7de0be2
8 changed files with 194 additions and 174 deletions
@@ -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<MavenProjectWithHolder>,
embeddersManager: MavenEmbeddersManager,
console: MavenConsole,
process: MavenProgressIndicator,
reportUnresolvedToSyncConsole: Boolean) {
suspend fun resolvePlugins(mavenProjectsToResolvePlugins: Collection<MavenProjectWithHolder>,
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)
}
@@ -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)
}
}
}
@@ -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)
}
@@ -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<Pair<MavenId, NativeMavenProjectHolder>>,
progressIndicator: MavenProgressIndicator?,
console: MavenConsole?): List<PluginResolutionResponse> {
suspend fun resolvePlugins(mavenPluginRequests: Collection<Pair<MavenId, NativeMavenProjectHolder>>,
progressIndicator: MavenProgressIndicator?,
console: MavenConsole?): List<PluginResolutionResponse> {
val pluginResolutionRequests = ArrayList<PluginResolutionRequest>()
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<MavenArtifact> {
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 <R> runLongRunningTaskAsync(task: LongRunningEmbedderTask<R>,
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 <R> runLongRunningTask(embedder: MavenServerEmbedder,
longRunningTaskId: String,
task: LongRunningEmbedderTask<R>,
@@ -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<MavenProject>) : Map<MavenProject, MavenProjectChanges> {
return runBlockingMaybeCancellable {
return@runBlockingMaybeCancellable MavenFolderResolver(project).resolveFolders(mavenProjects)
}
}
@@ -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("""
<groupId>test</groupId>
<artifactId>parent</artifactId>
<version>1</version>
""".trimIndent())
val child = createModulePom("child",
"""
<groupId>test</groupId>
<artifactId>child</artifactId>
<version>1</version>
<parent>
<groupId>test</groupId>
<artifactId>parent</artifactId>
<version>1</version>
</parent>
""".trimIndent())
val listener = MyLoggingListener()
myTree.addListener(listener, getTestRootDisposable())
updateAll(myProjectPom, child)
val parentProject = myTree.findProject(myProjectPom)!!
val embeddersManager = MavenEmbeddersManager(myProject)
try {
val nativeProject = arrayOfNulls<NativeMavenProjectHolder>(1)
myTree.addListener(object : MavenProjectsTree.Listener {
override fun projectResolved(projectWithChanges: Pair<MavenProject, MavenProjectChanges>,
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)
}
}
@@ -735,81 +735,6 @@ public class MavenProjectsTreeReadingTest extends MavenProjectsTreeTestCase {
assertNull(nativeProject.get(0));
}
@Test
public void testDoNotUpdateChildAfterParentWasResolved() throws Exception {
createProjectPom("""
<groupId>test</groupId>
<artifactId>parent</artifactId>
<version>1</version>
""");
VirtualFile child = createModulePom("child",
"""
<groupId>test</groupId>
<artifactId>child</artifactId>
<version>1</version>
<parent>
<groupId>test</groupId>
<artifactId>parent</artifactId>
<version>1</version>
</parent>
""");
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<MavenProject, MavenProjectChanges> 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<Pair<String, Set<String>>> {
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<Pair<String, Set<String>>> log = new CopyOnWriteArrayList<>();
private void add(String key, Set<String> value) {
log.add(new Pair<>(key, value));
}
@Override
public void projectsUpdated(@NotNull List<Pair<MavenProject, MavenProjectChanges>> updated, @NotNull List<MavenProject> deleted) {
append(MavenUtil.collectFirsts(updated), "updated");
append(deleted, "deleted");
}
private void append(List<MavenProject> updated, String text) {
add(text, updated.stream().map(each -> each.getMavenId().getArtifactId()).collect(Collectors.toSet()));
}
@Override
public void projectResolved(@NotNull Pair<MavenProject, MavenProjectChanges> 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<MavenProject, MavenProjectChanges> projectWithChanges) {
add("folders", Set.of(projectWithChanges.first.getMavenId().getArtifactId()));
}
}
}
@@ -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<Pair<String, Set<String>>> {
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<Pair<String, Set<String>>> log = new CopyOnWriteArrayList<>();
private void add(String key, Set<String> value) {
log.add(new Pair<>(key, value));
}
@Override
public void projectsUpdated(@NotNull List<Pair<MavenProject, MavenProjectChanges>> updated, @NotNull List<MavenProject> deleted) {
append(MavenUtil.collectFirsts(updated), "updated");
append(deleted, "deleted");
}
private void append(List<MavenProject> updated, String text) {
add(text, updated.stream().map(each -> each.getMavenId().getArtifactId()).collect(Collectors.toSet()));
}
@Override
public void projectResolved(@NotNull Pair<MavenProject, MavenProjectChanges> 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<MavenProject, MavenProjectChanges> 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());
}
}