KtScratchExecutionSession: fix INRE
#EA-218701 Fixed
This commit is contained in:
+63
-42
@@ -7,13 +7,16 @@ 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.openapi.application.ReadAction
|
||||||
import com.intellij.openapi.diagnostic.ControlFlowException
|
import com.intellij.openapi.diagnostic.ControlFlowException
|
||||||
import com.intellij.openapi.module.Module
|
import com.intellij.openapi.module.Module
|
||||||
import com.intellij.openapi.progress.ProgressIndicator
|
import com.intellij.openapi.progress.ProgressIndicator
|
||||||
import com.intellij.openapi.progress.Task
|
import com.intellij.openapi.progress.Task
|
||||||
import com.intellij.openapi.project.DumbService
|
import com.intellij.openapi.project.DumbService
|
||||||
|
import com.intellij.openapi.project.Project
|
||||||
import com.intellij.openapi.util.Computable
|
import com.intellij.openapi.util.Computable
|
||||||
import com.intellij.openapi.util.io.FileUtil
|
import com.intellij.openapi.util.io.FileUtil
|
||||||
|
import com.intellij.util.concurrency.NonUrgentExecutor
|
||||||
import org.jetbrains.kotlin.codegen.ClassBuilderFactories
|
import org.jetbrains.kotlin.codegen.ClassBuilderFactories
|
||||||
import org.jetbrains.kotlin.codegen.KotlinCodegenFacade
|
import org.jetbrains.kotlin.codegen.KotlinCodegenFacade
|
||||||
import org.jetbrains.kotlin.codegen.filterClassFiles
|
import org.jetbrains.kotlin.codegen.filterClassFiles
|
||||||
@@ -39,6 +42,7 @@ class KtScratchExecutionSession(
|
|||||||
private const val TIMEOUT_MS = 30000
|
private const val TIMEOUT_MS = 30000
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Volatile
|
||||||
private var backgroundProcessIndicator: ProgressIndicator? = null
|
private var backgroundProcessIndicator: ProgressIndicator? = null
|
||||||
|
|
||||||
fun execute(callback: () -> Unit) {
|
fun execute(callback: () -> Unit) {
|
||||||
@@ -47,57 +51,74 @@ class KtScratchExecutionSession(
|
|||||||
val expressions = file.getExpressions()
|
val expressions = file.getExpressions()
|
||||||
if (!executor.checkForErrors(psiFile, expressions)) return
|
if (!executor.checkForErrors(psiFile, expressions)) return
|
||||||
|
|
||||||
when (val result = runReadAction { KtScratchSourceFileProcessor().process(expressions) }) {
|
val project = file.project
|
||||||
is KtScratchSourceFileProcessor.Result.Error -> return executor.errorOccurs(result.message, isFatal = true)
|
ReadAction.nonBlocking {
|
||||||
is KtScratchSourceFileProcessor.Result.OK -> {
|
when (val result = KtScratchSourceFileProcessor().process(expressions)) {
|
||||||
LOG.printDebugMessage("After processing by KtScratchSourceFileProcessor:\n ${result.code}")
|
is KtScratchSourceFileProcessor.Result.Error -> return@nonBlocking executor.errorOccurs(result.message, isFatal = true)
|
||||||
|
is KtScratchSourceFileProcessor.Result.OK -> {
|
||||||
|
LOG.printDebugMessage("After processing by KtScratchSourceFileProcessor:\n ${result.code}")
|
||||||
|
|
||||||
object : Task.Backgroundable(psiFile.project, "Running Kotlin Scratch...", true) {
|
object : Task.Backgroundable(psiFile.project, "Running Kotlin Scratch...", true) {
|
||||||
override fun run(indicator: ProgressIndicator) {
|
override fun run(indicator: ProgressIndicator) {
|
||||||
backgroundProcessIndicator = indicator
|
backgroundProcessIndicator = indicator
|
||||||
|
|
||||||
val modifiedScratchSourceFile = runReadAction {
|
val modifiedScratchSourceFile = runReadAction {
|
||||||
KtPsiFactory(psiFile.project).createFileWithLightClassSupport("tmp.kt", result.code, psiFile)
|
KtPsiFactory(psiFile.project).createFileWithLightClassSupport("tmp.kt", result.code, psiFile)
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
val tempDir = DumbService.getInstance(project).runReadActionInSmartMode(
|
|
||||||
Computable {
|
|
||||||
compileFileToTempDir(modifiedScratchSourceFile, expressions)
|
|
||||||
}
|
}
|
||||||
) ?: return
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
val commandLine = createCommandLine(psiFile, file.module, result.mainClassName, tempDir.path)
|
runCommandLine(project, modifiedScratchSourceFile, expressions, psiFile, result, indicator, callback)
|
||||||
|
} catch (e: Throwable) {
|
||||||
|
if (e is ControlFlowException) throw e
|
||||||
|
|
||||||
LOG.printDebugMessage(commandLine.commandLineString)
|
LOG.printDebugMessage(result.code)
|
||||||
|
executor.errorOccurs(e.message ?: "Couldn't compile ${psiFile.name}", e, isFatal = true)
|
||||||
val processHandler = CapturingProcessHandler(commandLine)
|
|
||||||
val executionResult = processHandler.runProcessWithProgressIndicator(indicator, TIMEOUT_MS)
|
|
||||||
when {
|
|
||||||
executionResult.isTimeout -> {
|
|
||||||
executor.errorOccurs("Couldn't get scratch execution result - stopped by timeout ($TIMEOUT_MS ms)")
|
|
||||||
}
|
|
||||||
executionResult.isCancelled -> {
|
|
||||||
// ignore
|
|
||||||
}
|
|
||||||
else -> {
|
|
||||||
executor.parseOutput(executionResult, expressions)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} finally {
|
|
||||||
tempDir.delete()
|
|
||||||
callback()
|
|
||||||
}
|
}
|
||||||
} catch (e: Throwable) {
|
}.queue()
|
||||||
if (e is ControlFlowException) throw e
|
|
||||||
|
|
||||||
LOG.printDebugMessage(result.code)
|
|
||||||
executor.errorOccurs(e.message ?: "Couldn't compile ${psiFile.name}", e, isFatal = true)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}.queue()
|
}
|
||||||
}
|
}
|
||||||
|
.inSmartMode(project)
|
||||||
|
.expireWith(project)
|
||||||
|
.withDocumentsCommitted(project)
|
||||||
|
.submit(NonUrgentExecutor.getInstance())
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun runCommandLine(
|
||||||
|
project: Project,
|
||||||
|
modifiedScratchSourceFile: KtFile,
|
||||||
|
expressions: List<ScratchExpression>,
|
||||||
|
psiFile: KtFile,
|
||||||
|
result: KtScratchSourceFileProcessor.Result.OK,
|
||||||
|
indicator: ProgressIndicator,
|
||||||
|
callback: () -> Unit
|
||||||
|
) {
|
||||||
|
val tempDir = DumbService.getInstance(project).runReadActionInSmartMode(Computable {
|
||||||
|
compileFileToTempDir(modifiedScratchSourceFile, expressions)
|
||||||
|
}) ?: return
|
||||||
|
|
||||||
|
try {
|
||||||
|
val commandLine = createCommandLine(psiFile, file.module, result.mainClassName, tempDir.path)
|
||||||
|
|
||||||
|
LOG.printDebugMessage(commandLine.commandLineString)
|
||||||
|
|
||||||
|
val processHandler = CapturingProcessHandler(commandLine)
|
||||||
|
val executionResult = processHandler.runProcessWithProgressIndicator(indicator, TIMEOUT_MS)
|
||||||
|
when {
|
||||||
|
executionResult.isTimeout -> {
|
||||||
|
executor.errorOccurs("Couldn't get scratch execution result - stopped by timeout ($TIMEOUT_MS ms)")
|
||||||
|
}
|
||||||
|
executionResult.isCancelled -> {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
executor.parseOutput(executionResult, expressions)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
tempDir.delete()
|
||||||
|
callback()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user