mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-02-04 15:06:56 +07:00
[java] rewrite UnloadedModulesCompilationCheckinHandler to run computations on a background thread (IDEA-308600)
GitOrigin-RevId: 8e63afc07ae258aa557bf0d7e49c6c259725c90a
This commit is contained in:
committed by
intellij-monorepo-bot
parent
86d86261f0
commit
4167f4a603
@@ -1,33 +1,33 @@
|
|||||||
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||||
package com.intellij.compiler.impl.vcs
|
package com.intellij.compiler.impl.vcs
|
||||||
|
|
||||||
import com.intellij.CommonBundle
|
import com.intellij.build.BuildContentManager
|
||||||
import com.intellij.compiler.CompilerWorkspaceConfiguration
|
import com.intellij.compiler.CompilerWorkspaceConfiguration
|
||||||
import com.intellij.compiler.impl.ModuleCompileScope
|
import com.intellij.compiler.impl.ModuleCompileScope
|
||||||
import com.intellij.openapi.application.ApplicationManager
|
import com.intellij.openapi.application.ApplicationManager
|
||||||
|
import com.intellij.openapi.application.EDT
|
||||||
import com.intellij.openapi.application.ModalityState
|
import com.intellij.openapi.application.ModalityState
|
||||||
|
import com.intellij.openapi.application.readAction
|
||||||
import com.intellij.openapi.compiler.CompilerManager
|
import com.intellij.openapi.compiler.CompilerManager
|
||||||
import com.intellij.openapi.compiler.JavaCompilerBundle
|
import com.intellij.openapi.compiler.JavaCompilerBundle
|
||||||
import com.intellij.openapi.module.ModuleManager
|
import com.intellij.openapi.module.ModuleManager
|
||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
import com.intellij.openapi.roots.ProjectFileIndex
|
import com.intellij.openapi.roots.ProjectFileIndex
|
||||||
import com.intellij.openapi.roots.impl.DirectoryIndex
|
import com.intellij.openapi.roots.impl.DirectoryIndex
|
||||||
import com.intellij.openapi.ui.Messages
|
|
||||||
import com.intellij.openapi.vcs.CheckinProjectPanel
|
import com.intellij.openapi.vcs.CheckinProjectPanel
|
||||||
import com.intellij.openapi.vcs.changes.CommitContext
|
import com.intellij.openapi.vcs.changes.CommitContext
|
||||||
import com.intellij.openapi.vcs.changes.CommitExecutor
|
|
||||||
import com.intellij.openapi.vcs.changes.ui.BooleanCommitOption.Companion.create
|
import com.intellij.openapi.vcs.changes.ui.BooleanCommitOption.Companion.create
|
||||||
import com.intellij.openapi.vcs.checkin.CheckinHandler
|
import com.intellij.openapi.vcs.checkin.*
|
||||||
import com.intellij.openapi.vcs.checkin.CheckinHandlerFactory
|
|
||||||
import com.intellij.openapi.vcs.ui.RefreshableOnComponent
|
import com.intellij.openapi.vcs.ui.RefreshableOnComponent
|
||||||
import com.intellij.openapi.wm.ToolWindowId
|
|
||||||
import com.intellij.openapi.wm.ToolWindowManager
|
import com.intellij.openapi.wm.ToolWindowManager
|
||||||
import com.intellij.util.PairConsumer
|
import com.intellij.util.io.await
|
||||||
import com.intellij.xml.util.XmlStringUtil
|
import kotlinx.coroutines.Dispatchers
|
||||||
import java.util.concurrent.atomic.AtomicReference
|
import kotlinx.coroutines.withContext
|
||||||
|
import java.util.concurrent.CompletableFuture
|
||||||
|
|
||||||
class UnloadedModulesCompilationCheckinHandler(private val project: Project,
|
class UnloadedModulesCompilationCheckinHandler(private val project: Project,
|
||||||
private val checkinPanel: CheckinProjectPanel) : CheckinHandler() {
|
private val checkinPanel: CheckinProjectPanel) : CheckinHandler(), CommitCheck {
|
||||||
|
|
||||||
override fun getBeforeCheckinConfigurationPanel(): RefreshableOnComponent? {
|
override fun getBeforeCheckinConfigurationPanel(): RefreshableOnComponent? {
|
||||||
return if (ModuleManager.getInstance(project).unloadedModuleDescriptions.isNotEmpty())
|
return if (ModuleManager.getInstance(project).unloadedModuleDescriptions.isNotEmpty())
|
||||||
create(checkinPanel.getProject(), this, false,
|
create(checkinPanel.getProject(), this, false,
|
||||||
@@ -40,61 +40,69 @@ class UnloadedModulesCompilationCheckinHandler(private val project: Project,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun beforeCheckin(executor: CommitExecutor?, additionalDataConsumer: PairConsumer<Any, Any>): ReturnResult {
|
override suspend fun runCheck(commitInfo: CommitInfo): CommitProblem? = withContext(Dispatchers.Default) {
|
||||||
if (!settings.COMPILE_AFFECTED_UNLOADED_MODULES_BEFORE_COMMIT ||
|
val unloadedModulesCompileScope = readAction {
|
||||||
ModuleManager.getInstance(project).unloadedModuleDescriptions.isEmpty()) {
|
if (ModuleManager.getInstance(project).unloadedModuleDescriptions.isEmpty()) {
|
||||||
return ReturnResult.COMMIT
|
return@readAction null
|
||||||
|
}
|
||||||
|
val fileIndex = ProjectFileIndex.getInstance(project)
|
||||||
|
val compilerManager = CompilerManager.getInstance(project)
|
||||||
|
val affectedModules = checkinPanel.getVirtualFiles()
|
||||||
|
.filter { compilerManager.isCompilableFileType(it.fileType) }
|
||||||
|
.mapNotNullTo(LinkedHashSet()) { fileIndex.getModuleForFile(it) }
|
||||||
|
val affectedUnloadedModules = affectedModules.flatMapTo(LinkedHashSet()) {
|
||||||
|
DirectoryIndex.getInstance(project).getDependentUnloadedModules(it)
|
||||||
|
}
|
||||||
|
if (affectedUnloadedModules.isEmpty()) {
|
||||||
|
return@readAction null
|
||||||
|
}
|
||||||
|
ModuleCompileScope(project, affectedModules, affectedUnloadedModules, true, false)
|
||||||
}
|
}
|
||||||
val fileIndex = ProjectFileIndex.getInstance(project)
|
if (unloadedModulesCompileScope == null) {
|
||||||
val compilerManager = CompilerManager.getInstance(project)
|
return@withContext null
|
||||||
val affectedModules = checkinPanel.getVirtualFiles()
|
|
||||||
.filter { compilerManager.isCompilableFileType(it.fileType) }
|
|
||||||
.mapNotNullTo(LinkedHashSet()) { fileIndex.getModuleForFile(it) }
|
|
||||||
val affectedUnloadedModules = affectedModules.flatMapTo(LinkedHashSet()) {
|
|
||||||
DirectoryIndex.getInstance(project).getDependentUnloadedModules(it)
|
|
||||||
}
|
}
|
||||||
if (affectedUnloadedModules.isEmpty()) {
|
|
||||||
return ReturnResult.COMMIT
|
val compiledSuccessfully = CompletableFuture<Boolean>()
|
||||||
}
|
withContext(Dispatchers.EDT) {
|
||||||
val result = AtomicReference<BuildResult>()
|
CompilerManager.getInstance(project).make(unloadedModulesCompileScope) { aborted, errors, _, _ ->
|
||||||
compilerManager.makeWithModalProgress(ModuleCompileScope(project, affectedModules, affectedUnloadedModules, true, false)) { aborted, errors, _, _ ->
|
if (aborted) {
|
||||||
result.set(when {
|
compiledSuccessfully.cancel(true)
|
||||||
aborted -> BuildResult.CANCELED
|
}
|
||||||
errors > 0 -> BuildResult.FAILED
|
else {
|
||||||
else -> BuildResult.SUCCESSFUL
|
compiledSuccessfully.complete(errors == 0)
|
||||||
})
|
}
|
||||||
}
|
|
||||||
if (result.get() == BuildResult.SUCCESSFUL) {
|
|
||||||
return ReturnResult.COMMIT
|
|
||||||
}
|
|
||||||
val message = JavaCompilerBundle.message("dialog.message.compilation.of.unloaded.modules.failed")
|
|
||||||
val answer = Messages.showYesNoCancelDialog(project, XmlStringUtil.wrapInHtml(message), JavaCompilerBundle
|
|
||||||
.message("dialog.title.compilation.failed"),
|
|
||||||
JavaCompilerBundle.message("button.text.checkin.handler.commit"),
|
|
||||||
JavaCompilerBundle.message("button.text.checkin.handler.show.errors"),
|
|
||||||
CommonBundle.getCancelButtonText(), null)
|
|
||||||
return when (answer) {
|
|
||||||
Messages.CANCEL -> ReturnResult.CANCEL
|
|
||||||
Messages.YES -> ReturnResult.COMMIT
|
|
||||||
else -> {
|
|
||||||
ApplicationManager.getApplication().invokeLater({
|
|
||||||
val toolWindow = ToolWindowManager.getInstance(project).getToolWindow(ToolWindowId.MESSAGES_WINDOW)
|
|
||||||
toolWindow?.activate(null, false)
|
|
||||||
}, ModalityState.nonModal())
|
|
||||||
ReturnResult.CLOSE_WINDOW
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (compiledSuccessfully.await()) {
|
||||||
|
return@withContext null
|
||||||
|
}
|
||||||
|
return@withContext CompilationFailedProblem()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun getExecutionOrder(): CommitCheck.ExecutionOrder = CommitCheck.ExecutionOrder.LATE
|
||||||
|
|
||||||
|
override fun isEnabled(): Boolean = settings.COMPILE_AFFECTED_UNLOADED_MODULES_BEFORE_COMMIT
|
||||||
|
|
||||||
private val settings: CompilerWorkspaceConfiguration
|
private val settings: CompilerWorkspaceConfiguration
|
||||||
get() = CompilerWorkspaceConfiguration.getInstance(project)
|
get() = CompilerWorkspaceConfiguration.getInstance(project)
|
||||||
|
|
||||||
private enum class BuildResult {
|
class CompilationFailedProblem : CommitProblemWithDetails {
|
||||||
SUCCESSFUL,
|
override val text: String
|
||||||
FAILED,
|
get() = JavaCompilerBundle.message("dialog.message.compilation.of.unloaded.modules.failed")
|
||||||
CANCELED
|
override val showDetailsAction: String
|
||||||
}
|
get() = JavaCompilerBundle.message("button.text.checkin.handler.show.errors")
|
||||||
|
override val showDetailsLink: String
|
||||||
|
get() = JavaCompilerBundle.message("link.label.checkin.handler.show.errors")
|
||||||
|
|
||||||
|
override fun showDetails(project: Project) {
|
||||||
|
ApplicationManager.getApplication().invokeLater({
|
||||||
|
val toolWindow = ToolWindowManager.getInstance(project).getToolWindow(BuildContentManager.TOOL_WINDOW_ID)
|
||||||
|
toolWindow?.activate(null, false)
|
||||||
|
}, ModalityState.nonModal())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class Factory : CheckinHandlerFactory() {
|
class Factory : CheckinHandlerFactory() {
|
||||||
override fun createHandler(panel: CheckinProjectPanel, commitContext: CommitContext): CheckinHandler {
|
override fun createHandler(panel: CheckinProjectPanel, commitContext: CommitContext): CheckinHandler {
|
||||||
return UnloadedModulesCompilationCheckinHandler(panel.getProject(), panel)
|
return UnloadedModulesCompilationCheckinHandler(panel.getProject(), panel)
|
||||||
|
|||||||
@@ -97,11 +97,10 @@ mesage.text.deployment.descriptor.file.not.exist=Deployment descriptor file ''{0
|
|||||||
message.text.deployment.description.invalid.file=Invalid file
|
message.text.deployment.description.invalid.file=Invalid file
|
||||||
warning.text.file.has.been.changed=File has been changed during compilation, inspection validation skipped
|
warning.text.file.has.been.changed=File has been changed during compilation, inspection validation skipped
|
||||||
|
|
||||||
dialog.message.compilation.of.unloaded.modules.failed=There are unloaded modules in the project which depend on changed files.<br>\
|
dialog.message.compilation.of.unloaded.modules.failed=There are unloaded modules in the project which depend on changed files.\n\
|
||||||
Compilation of these modules finished with errors.
|
Compilation of these modules finished with errors.
|
||||||
dialog.title.compilation.failed=Compilation Failed
|
|
||||||
button.text.checkin.handler.commit=&Commit
|
|
||||||
button.text.checkin.handler.show.errors=&Show Errors
|
button.text.checkin.handler.show.errors=&Show Errors
|
||||||
|
link.label.checkin.handler.show.errors=Show errors
|
||||||
checkbox.text.compile.affected.unloaded.modules=Compile affected &unloaded modules
|
checkbox.text.compile.affected.unloaded.modules=Compile affected &unloaded modules
|
||||||
|
|
||||||
#artifacts
|
#artifacts
|
||||||
|
|||||||
Reference in New Issue
Block a user