Run Kotlin Scratch in the background cancelable task (KT-25032)
KT-25032 Fixed
This commit is contained in:
+34
-21
@@ -19,9 +19,10 @@ package org.jetbrains.kotlin.idea.scratch.compile
|
|||||||
import com.intellij.execution.configurations.GeneralCommandLine
|
import com.intellij.execution.configurations.GeneralCommandLine
|
||||||
import com.intellij.execution.process.CapturingProcessHandler
|
import com.intellij.execution.process.CapturingProcessHandler
|
||||||
import com.intellij.execution.process.ProcessOutput
|
import com.intellij.execution.process.ProcessOutput
|
||||||
import com.intellij.openapi.application.ApplicationManager
|
|
||||||
import com.intellij.openapi.compiler.ex.CompilerPathsEx
|
import com.intellij.openapi.compiler.ex.CompilerPathsEx
|
||||||
import com.intellij.openapi.module.Module
|
import com.intellij.openapi.module.Module
|
||||||
|
import com.intellij.openapi.progress.ProgressIndicator
|
||||||
|
import com.intellij.openapi.progress.Task
|
||||||
import com.intellij.openapi.roots.OrderEnumerator
|
import com.intellij.openapi.roots.OrderEnumerator
|
||||||
import com.intellij.openapi.util.io.FileUtil
|
import com.intellij.openapi.util.io.FileUtil
|
||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
@@ -51,6 +52,10 @@ import org.jetbrains.kotlin.resolve.AnalyzingUtils
|
|||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
class KtCompilingExecutor(file: ScratchFile) : ScratchExecutor(file) {
|
class KtCompilingExecutor(file: ScratchFile) : ScratchExecutor(file) {
|
||||||
|
companion object {
|
||||||
|
private val TIMEOUT_MS = 30000
|
||||||
|
}
|
||||||
|
|
||||||
override fun execute() {
|
override fun execute() {
|
||||||
val module = file.getModule() ?: return error("Module should be selected")
|
val module = file.getModule() ?: return error("Module should be selected")
|
||||||
val psiFile = file.getPsiFile() as? KtFile ?: return error("Couldn't find KtFile for current editor")
|
val psiFile = file.getPsiFile() as? KtFile ?: return error("Couldn't find KtFile for current editor")
|
||||||
@@ -63,32 +68,40 @@ class KtCompilingExecutor(file: ScratchFile) : ScratchExecutor(file) {
|
|||||||
when (result) {
|
when (result) {
|
||||||
is KtScratchSourceFileProcessor.Result.Error -> return error(result.message)
|
is KtScratchSourceFileProcessor.Result.Error -> return error(result.message)
|
||||||
is KtScratchSourceFileProcessor.Result.OK -> {
|
is KtScratchSourceFileProcessor.Result.OK -> {
|
||||||
ApplicationManager.getApplication().invokeLater {
|
LOG.printDebugMessage("After processing by KtScratchSourceFileProcessor:\n ${result.code}")
|
||||||
LOG.printDebugMessage("After processing by KtScratchSourceFileProcessor:\n ${result.code}")
|
|
||||||
|
|
||||||
val modifiedScratchSourceFile =
|
object : Task.Backgroundable(psiFile.project, "Running Kotlin Scratch...", true) {
|
||||||
KtPsiFactory(psiFile.project).createFileWithLightClassSupport("tmp.kt", result.code, psiFile)
|
override fun run(indicator: ProgressIndicator) {
|
||||||
|
val modifiedScratchSourceFile = runReadAction {
|
||||||
try {
|
KtPsiFactory(psiFile.project).createFileWithLightClassSupport("tmp.kt", result.code, psiFile)
|
||||||
val tempDir = compileFileToTempDir(modifiedScratchSourceFile) ?: return@invokeLater
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
val commandLine = createCommandLine(module, result.mainClassName, tempDir.path)
|
val tempDir = runReadAction { compileFileToTempDir(modifiedScratchSourceFile) } ?: return
|
||||||
|
|
||||||
LOG.printDebugMessage(commandLine.commandLineString)
|
try {
|
||||||
|
val commandLine = createCommandLine(module, result.mainClassName, tempDir.path)
|
||||||
|
|
||||||
val handler = CapturingProcessHandler(commandLine)
|
LOG.printDebugMessage(commandLine.commandLineString)
|
||||||
ProcessOutputParser().parse(handler.runProcess())
|
|
||||||
|
val handler = CapturingProcessHandler(commandLine)
|
||||||
|
val executionResult = handler.runProcessWithProgressIndicator(indicator, TIMEOUT_MS)
|
||||||
|
when {
|
||||||
|
executionResult.isTimeout -> error("Couldn't get scratch execution result - stopped by timeout ($TIMEOUT_MS ms)")
|
||||||
|
executionResult.isCancelled -> error("Couldn't get scratch execution result - cancelled by user")
|
||||||
|
else -> ProcessOutputParser().parse(executionResult)
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
tempDir.delete()
|
||||||
|
}
|
||||||
|
} catch (e: Throwable) {
|
||||||
|
LOG.info(result.code, e)
|
||||||
|
handlers.forEach { it.error(file, e.message ?: "Couldn't compile ${psiFile.name}") }
|
||||||
} finally {
|
} finally {
|
||||||
tempDir.delete()
|
handlers.forEach { it.onFinish(file) }
|
||||||
}
|
}
|
||||||
} catch (e: Throwable) {
|
|
||||||
LOG.info(result.code, e)
|
|
||||||
handlers.forEach { it.error(file, e.message ?: "Couldn't compile ${psiFile.name}") }
|
|
||||||
} finally {
|
|
||||||
handlers.forEach { it.onFinish(file) }
|
|
||||||
}
|
}
|
||||||
}
|
}.queue()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -206,11 +219,11 @@ class KtCompilingExecutor(file: ScratchFile) : ScratchExecutor(file) {
|
|||||||
|
|
||||||
private fun ScratchFile.findExpression(psiElement: PsiElement): ScratchExpression? {
|
private fun ScratchFile.findExpression(psiElement: PsiElement): ScratchExpression? {
|
||||||
val elementLine = psiElement.getLineNumber()
|
val elementLine = psiElement.getLineNumber()
|
||||||
return getExpressions().firstOrNull { elementLine in it.lineStart..it.lineEnd }
|
return runReadAction { getExpressions().firstOrNull { elementLine in it.lineStart..it.lineEnd } }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun ScratchFile.findExpression(lineStart: Int, lineEnd: Int): ScratchExpression? {
|
private fun ScratchFile.findExpression(lineStart: Int, lineEnd: Int): ScratchExpression? {
|
||||||
return getExpressions().firstOrNull { it.lineStart == lineStart && it.lineEnd == lineEnd }
|
return runReadAction { getExpressions().firstOrNull { it.lineStart == lineStart && it.lineEnd == lineEnd } }
|
||||||
}
|
}
|
||||||
|
|
||||||
private inner class ProcessOutputParser {
|
private inner class ProcessOutputParser {
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ import com.intellij.ide.scratch.ScratchFileService
|
|||||||
import com.intellij.ide.scratch.ScratchRootType
|
import com.intellij.ide.scratch.ScratchRootType
|
||||||
import com.intellij.openapi.actionSystem.AnAction
|
import com.intellij.openapi.actionSystem.AnAction
|
||||||
import com.intellij.openapi.actionSystem.CommonDataKeys
|
import com.intellij.openapi.actionSystem.CommonDataKeys
|
||||||
import com.intellij.openapi.project.Project
|
|
||||||
import com.intellij.openapi.roots.CompilerModuleExtension
|
import com.intellij.openapi.roots.CompilerModuleExtension
|
||||||
import com.intellij.openapi.roots.ModuleRootModificationUtil
|
import com.intellij.openapi.roots.ModuleRootModificationUtil
|
||||||
import com.intellij.openapi.util.io.FileUtil
|
import com.intellij.openapi.util.io.FileUtil
|
||||||
@@ -161,7 +160,8 @@ abstract class AbstractScratchRunActionTest : FileEditorManagerTestCase() {
|
|||||||
private fun getActionEvent(virtualFile: VirtualFile, action: AnAction): TestActionEvent {
|
private fun getActionEvent(virtualFile: VirtualFile, action: AnAction): TestActionEvent {
|
||||||
val context = MapDataContext()
|
val context = MapDataContext()
|
||||||
context.put(CommonDataKeys.VIRTUAL_FILE_ARRAY, arrayOf(virtualFile))
|
context.put(CommonDataKeys.VIRTUAL_FILE_ARRAY, arrayOf(virtualFile))
|
||||||
context.put<Project>(CommonDataKeys.PROJECT, project)
|
context.put(CommonDataKeys.PROJECT, project)
|
||||||
|
context.put(CommonDataKeys.EDITOR, myFixture.editor)
|
||||||
return TestActionEvent(context, action)
|
return TestActionEvent(context, action)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user