[Gradle] wait for import finish during project preparation for opening in headless or automated environments IDEA-277743

GitOrigin-RevId: ffd7cc30804fe18dd593ca15647dc2b692a5b4fc
This commit is contained in:
Vladislav.Soroka
2021-09-09 10:02:28 +00:00
committed by intellij-monorepo-bot
parent c7f1674c7b
commit cc6023df72
@@ -1,4 +1,4 @@
// Copyright 2000-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package org.jetbrains.plugins.gradle
import com.intellij.ide.CommandLineInspectionProjectConfigurator
@@ -8,7 +8,9 @@ import com.intellij.openapi.diagnostic.Logger
import com.intellij.openapi.externalSystem.autoimport.AutoImportProjectTracker
import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskId
import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskNotificationListenerAdapter
import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskType
import com.intellij.openapi.externalSystem.service.notification.ExternalSystemProgressNotificationManager
import com.intellij.openapi.externalSystem.service.project.manage.ProjectDataImportListener
import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil
import com.intellij.openapi.project.Project
import com.intellij.openapi.util.io.FileUtil
@@ -54,12 +56,13 @@ class GradleCommandLineProjectConfigurator : CommandLineInspectionProjectConfigu
linkProjects(basePath, project)
}
val progressManager = ExternalSystemProgressNotificationManager.getInstance()
val notificationListener = StateNotificationListener()
val notificationListener = StateNotificationListener(project)
try {
progressManager.addNotificationListener(notificationListener)
importProjects(project)
notificationListener.waitForImportEnd()
} finally {
}
finally {
progressManager.removeNotificationListener(notificationListener)
}
}
@@ -114,42 +117,54 @@ class GradleCommandLineProjectConfigurator : CommandLineInspectionProjectConfigu
}
class StateNotificationListener : ExternalSystemTaskNotificationListenerAdapter() {
class StateNotificationListener(private val project: Project) : ExternalSystemTaskNotificationListenerAdapter() {
private val externalSystemState = ConcurrentHashMap<ExternalSystemTaskId, CompletableFuture<ExternalSystemTaskId>>()
override fun onSuccess(id: ExternalSystemTaskId) {
LOG.info("Gradle import success: ${id.ideProjectId}")
val future = externalSystemState[id] ?: return
future.complete(id)
if (!id.isGradleProjectResolveTask()) return
LOG.info("Gradle resolve success: ${id.ideProjectId}")
val connection = project.messageBus.simpleConnect()
connection.subscribe(ProjectDataImportListener.TOPIC, object : ProjectDataImportListener {
override fun onImportFinished(projectPath: String?) {
LOG.info("Gradle import success: ${id.ideProjectId}")
val future = externalSystemState[id] ?: return
future.complete(id)
}
override fun onImportFailed(projectPath: String?) {
LOG.info("Gradle import failure: ${id.ideProjectId}")
val future = externalSystemState[id] ?: return
future.completeExceptionally(IllegalStateException("Gradle project ${id.ideProjectId} import failed."))
}
})
}
override fun onFailure(id: ExternalSystemTaskId, e: Exception) {
LOG.error("Gradle import failure ${id.ideProjectId}", e)
if (!id.isGradleProjectResolveTask()) return
LOG.error("Gradle resolve failure ${id.ideProjectId}", e)
val future = externalSystemState[id] ?: return
future.completeExceptionally(IllegalStateException("Gradle project ${id.ideProjectId} import failed.", e))
future.completeExceptionally(IllegalStateException("Gradle project ${id.ideProjectId} resolve failed.", e))
}
override fun onCancel(id: ExternalSystemTaskId) {
LOG.error("Gradle import canceled ${id.ideProjectId}")
if (!id.isGradleProjectResolveTask()) return
LOG.error("Gradle resolve canceled ${id.ideProjectId}")
val future = externalSystemState[id] ?: return
future.completeExceptionally(IllegalStateException("Import of ${id.ideProjectId} was canceled"))
future.completeExceptionally(IllegalStateException("Resolve of ${id.ideProjectId} was canceled"))
}
override fun onStart(id: ExternalSystemTaskId) {
if (!id.isGradleProjectResolveTask()) return
externalSystemState[id] = CompletableFuture()
LOG.info("Gradle import started ${id.ideProjectId}")
LOG.info("Gradle project resolve started ${id.ideProjectId}")
}
fun waitForImportEnd() {
externalSystemState.values.forEach { it.get() }
}
override fun onEnd(id: ExternalSystemTaskId) {
val future = externalSystemState[id] ?: return
if (future.isDone) return
LOG.error("Gradle import finished ${id.ideProjectId} without success event")
future.completeExceptionally(IllegalStateException("Import of ${id.ideProjectId} was finished without success event"))
}
private fun ExternalSystemTaskId.isGradleProjectResolveTask() = this.projectSystemId == GradleConstants.SYSTEM_ID &&
this.type == ExternalSystemTaskType.RESOLVE_PROJECT
}
class LoggingNotificationListener : ExternalSystemTaskNotificationListenerAdapter() {