Add support to cancel building Haskell tools

This commit is contained in:
Rik van der Kleij 2019-12-22 19:06:52 +01:00
parent e4e810fab6
commit 20d5059acb
4 changed files with 60 additions and 6 deletions

View File

@ -107,13 +107,13 @@ object StackProjectManager {
val title = (if (update) "Updating" else "Installing") + " Haskell tools"
ProgressManager.getInstance().run(new Task.Backgroundable(project, title, false, PerformInBackgroundOption.ALWAYS_BACKGROUND) {
ProgressManager.getInstance().run(new Task.Backgroundable(project, title, true, PerformInBackgroundOption.ALWAYS_BACKGROUND) {
private def isToolAvailable(progressIndicator: ProgressIndicator, tool: HTool) = {
HaskellSettingsState.useCustomTools || {
if (!GlobalInfo.toolPath(tool).exists() || update) {
progressIndicator.setText(s"Busy with installing ${tool.name} in ${GlobalInfo.toolsBinPath}")
StackCommandLine.installTool(project, tool.name)
StackCommandLine.installTool(project, progressIndicator, tool.name)
} else {
true
}

View File

@ -19,9 +19,11 @@ package intellij.haskell.external.execution
import com.intellij.execution.configurations.GeneralCommandLine
import com.intellij.execution.configurations.GeneralCommandLine.ParentEnvironmentType
import com.intellij.execution.process._
import com.intellij.openapi.progress.ProgressIndicator
import com.intellij.openapi.project.Project
import com.intellij.openapi.util.Key
import com.intellij.openapi.vfs.VfsUtil
import com.intellij.util.io.BaseOutputReader
import intellij.haskell.HaskellNotificationGroup
import org.jetbrains.jps.incremental.messages.BuildMessage
import org.jetbrains.jps.incremental.messages.BuildMessage.Kind
@ -50,6 +52,23 @@ object CommandLine {
run3(None, VfsUtil.getUserHomeDir.getPath, commandPath, arguments, timeoutInMillis, notifyBalloonError, ignoreExitCode, logOutput)
}
def runWithProgressIndicator(project: Project, workDir: Option[String], commandPath: String, arguments: Seq[String], progressIndicator: Option[ProgressIndicator]): CapturingProcessHandler = {
val commandLine = createCommandLine(workDir.getOrElse(project.getBasePath), commandPath, arguments)
new CapturingProcessHandler(commandLine) {
override protected def createProcessAdapter(processOutput: ProcessOutput): CapturingProcessAdapter = {
progressIndicator match {
case Some(pi) => new CapturingProcessToProgressIndicator(project, pi)
case None => super.createProcessAdapter(processOutput)
}
}
override def readerOptions(): BaseOutputReader.Options = {
BaseOutputReader.Options.NON_BLOCKING
}
}
}
private def run3(project: Option[Project], workDir: String, commandPath: String, arguments: Seq[String], timeoutInMillis: Long = DefaultTimeout.toMillis,
notifyBalloonError: Boolean = DefaultNotifyBalloonError, ignoreExitCode: Boolean = DefaultIgnoreExitCode, logOutput: Boolean = DefaultLogOutput): ProcessOutput = {
@ -121,6 +140,13 @@ private class CapturingProcessToLog(val project: Option[Project], val cmd: Gener
}
}
private class CapturingProcessToProgressIndicator(project: Project, progressIndicator: ProgressIndicator) extends CapturingProcessAdapter() {
override def onTextAvailable(event: ProcessEvent, outputType: Key[_]): Unit = {
progressIndicator.setText2(event.getText)
}
}
sealed trait CaptureOutput

View File

@ -59,7 +59,19 @@ object StackCommandLine {
})
}
def installTool(project: Project, toolName: String): Boolean = {
def runWithProgressIndicator(project: Project, workDir: Option[String], arguments: Seq[String], progressIndicator: Option[ProgressIndicator]): Option[CapturingProcessHandler] = {
HaskellSdkType.getStackBinaryPath(project).map(stackPath => {
CommandLine.runWithProgressIndicator(
project,
workDir,
stackPath,
arguments,
progressIndicator
)
})
}
def installTool(project: Project, progressIndicator: ProgressIndicator, toolName: String): Boolean = {
import intellij.haskell.GlobalInfo._
val systemGhcOption = if (StackYamlComponent.isNixEnabled(project) || !HaskellSettingsState.useSystemGhc) {
Seq()
@ -67,8 +79,21 @@ object StackCommandLine {
Seq("--system-ghc")
}
val arguments = systemGhcOption ++ Seq("-j1", "--stack-root", toolsStackRootPath.getPath, "--resolver", StackageLtsVersion, "--local-bin-path", toolsBinPath.getPath, "install", toolName)
val processOutput = run(project, arguments, -1, logOutput = true, notifyBalloonError = true, workDir = Some(VfsUtil.getUserHomeDir.getPath), enableExtraArguments = false)
processOutput.exists(o => o.getExitCode == 0 && !o.isTimeout)
val result = runWithProgressIndicator(project, workDir = Some(VfsUtil.getUserHomeDir.getPath), arguments, Some(progressIndicator)).exists(handler => {
val output = handler.runProcessWithProgressIndicator(progressIndicator)
if (output.isCancelled) {
handler.destroyProcess()
}
if (output.getExitCode != 0) {
HaskellNotificationGroup.logErrorBalloonEvent(project, output.getStderr)
}
output.getExitCode == 0 && !output.isCancelled && !output.isTimeout
})
result
}
def updateStackIndex(project: Project): Option[ProcessOutput] = {

View File

@ -23,6 +23,7 @@ import com.intellij.psi.util.PsiTreeUtil
import com.intellij.psi.{PsiDocumentManager, PsiElement, PsiFile}
import intellij.haskell.action.{HindentReformatAction, SelectionContext}
import intellij.haskell.annotator.HaskellAnnotator
import intellij.haskell.external.component.StackProjectManager
import intellij.haskell.psi.{HaskellElementFactory, HaskellPsiUtil, HaskellTypes}
import intellij.haskell.util.HaskellFileUtil
@ -71,7 +72,9 @@ class HLintQuickfix(startElement: PsiElement, endElement: PsiElement, startLineN
e.getTextRange.getEndOffset,
e.getText
)
HindentReformatAction.format(psiFile, Some(context))
if (StackProjectManager.isHindentAvailable(project)) {
HindentReformatAction.format(psiFile, Some(context))
}
})
HaskellFileUtil.saveFile(psiFile)