diff --git a/idea/idea-jvm/src/org/jetbrains/kotlin/idea/scratch/ScratchExecutor.kt b/idea/idea-jvm/src/org/jetbrains/kotlin/idea/scratch/ScratchExecutor.kt index 56f56a81406..2de25d66338 100644 --- a/idea/idea-jvm/src/org/jetbrains/kotlin/idea/scratch/ScratchExecutor.kt +++ b/idea/idea-jvm/src/org/jetbrains/kotlin/idea/scratch/ScratchExecutor.kt @@ -16,26 +16,54 @@ package org.jetbrains.kotlin.idea.scratch +import org.jetbrains.kotlin.idea.scratch.output.ScratchOutput import org.jetbrains.kotlin.idea.scratch.output.ScratchOutputHandler abstract class ScratchExecutor(protected val file: ScratchFile) { abstract fun execute() abstract fun stop() - protected val handlers = mutableListOf() + protected val handler = CompositeOutputHandler() fun addOutputHandler(outputHandler: ScratchOutputHandler) { - handlers.add(outputHandler) + handler.add(outputHandler) } fun errorOccurs(message: String, e: Throwable? = null, isFatal: Boolean = false) { - handlers.forEach { - it.error(file, message) - if (isFatal) { - it.onFinish(file) - } + handler.error(file, message) + + if (isFatal) { + handler.onFinish(file) } if (e != null) LOG.error(e) } + + protected class CompositeOutputHandler : ScratchOutputHandler { + private val handlers = mutableListOf() + + fun add(handler: ScratchOutputHandler) { + handlers.add(handler) + } + + override fun onStart(file: ScratchFile) { + handlers.forEach { it.onStart(file) } + } + + override fun handle(file: ScratchFile, expression: ScratchExpression, output: ScratchOutput) { + handlers.forEach { it.handle(file, expression, output) } + } + + override fun error(file: ScratchFile, message: String) { + handlers.forEach { it.error(file, message) } + } + + override fun onFinish(file: ScratchFile) { + handlers.forEach { it.onFinish(file) } + } + + override fun clear(file: ScratchFile) { + handlers.forEach { it.clear(file) } + } + } } \ No newline at end of file diff --git a/idea/idea-jvm/src/org/jetbrains/kotlin/idea/scratch/compile/KtCompilingExecutor.kt b/idea/idea-jvm/src/org/jetbrains/kotlin/idea/scratch/compile/KtCompilingExecutor.kt index 2bfad38662a..48c31bca019 100644 --- a/idea/idea-jvm/src/org/jetbrains/kotlin/idea/scratch/compile/KtCompilingExecutor.kt +++ b/idea/idea-jvm/src/org/jetbrains/kotlin/idea/scratch/compile/KtCompilingExecutor.kt @@ -61,7 +61,7 @@ class KtCompilingExecutor(file: ScratchFile) : ScratchExecutor(file) { private var backgroundProcessIndicator: ProgressIndicator? = null override fun execute() { - handlers.forEach { it.onStart(file) } + handler.onStart(file) 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") @@ -108,9 +108,9 @@ class KtCompilingExecutor(file: ScratchFile) : ScratchExecutor(file) { } } catch (e: Throwable) { LOG.info(result.code, e) - handlers.forEach { it.error(file, e.message ?: "Couldn't compile ${psiFile.name}") } + handler.error(file, e.message ?: "Couldn't compile ${psiFile.name}") } finally { - handlers.forEach { it.onFinish(file) } + handler.onFinish(file) } } }.queue() @@ -122,7 +122,7 @@ class KtCompilingExecutor(file: ScratchFile) : ScratchExecutor(file) { try { backgroundProcessIndicator?.cancel() } finally { - handlers.forEach { it.onFinish(file) } + handler.onFinish(file) } } @@ -192,14 +192,14 @@ class KtCompilingExecutor(file: ScratchFile) : ScratchExecutor(file) { try { AnalyzingUtils.checkForSyntacticErrors(psiFile) } catch (e: IllegalArgumentException) { - handlers.forEach { it.error(file, e.message ?: "Couldn't compile ${psiFile.name}") } + handler.error(file, e.message ?: "Couldn't compile ${psiFile.name}") return@runReadAction false } val analysisResult = psiFile.analyzeWithAllCompilerChecks() if (analysisResult.isError()) { - handlers.forEach { it.error(file, analysisResult.error.message ?: "Couldn't compile ${psiFile.name}") } + handler.error(file, analysisResult.error.message ?: "Couldn't compile ${psiFile.name}") return@runReadAction false } @@ -214,16 +214,16 @@ class KtCompilingExecutor(file: ScratchFile) : ScratchExecutor(file) { val scratchExpression = file.findExpression(diagnostic.psiElement) if (scratchExpression == null) { LOG.error("Couldn't find expression to report error: ${diagnostic.psiElement.getElementTextWithContext()}") - handlers.forEach { it.error(file, errorText) } + handler.error(file, errorText) } else { - handlers.forEach { it.handle(file, scratchExpression, ScratchOutput(errorText, ScratchOutputType.ERROR)) } + handler.handle(file, scratchExpression, ScratchOutput(errorText, ScratchOutputType.ERROR)) } } else { - handlers.forEach { it.error(file, errorText) } + handler.error(file, errorText) } } else { - handlers.forEach { it.error(file, errorText) } + handler.error(file, errorText) } } return@runReadAction false @@ -233,8 +233,8 @@ class KtCompilingExecutor(file: ScratchFile) : ScratchExecutor(file) { } private fun error(message: String) { - handlers.forEach { it.error(file, message) } - handlers.forEach { it.onFinish(file) } + handler.error(file, message) + handler.onFinish(file) } private fun ScratchFile.findExpression(psiElement: PsiElement): ScratchExpression? { @@ -251,7 +251,7 @@ class KtCompilingExecutor(file: ScratchFile) : ScratchExecutor(file) { val out = processOutput.stdout val err = processOutput.stderr if (err.isNotBlank()) { - handlers.forEach { it.error(file, err) } + handler.error(file, err) } if (out.isNotBlank()) { parseStdOut(out) @@ -282,15 +282,11 @@ class KtCompilingExecutor(file: ScratchFile) : ScratchExecutor(file) { ) } else { userOutput.forEach { output -> - handlers.forEach { - it.handle(file, scratchExpression, ScratchOutput(output, ScratchOutputType.OUTPUT)) - } + handler.handle(file, scratchExpression, ScratchOutput(output, ScratchOutputType.OUTPUT)) } results.forEach { result -> - handlers.forEach { - it.handle(file, scratchExpression, ScratchOutput(result, ScratchOutputType.RESULT)) - } + handler.handle(file, scratchExpression, ScratchOutput(result, ScratchOutputType.RESULT)) } } diff --git a/idea/idea-jvm/src/org/jetbrains/kotlin/idea/scratch/repl/KtScratchReplExecutor.kt b/idea/idea-jvm/src/org/jetbrains/kotlin/idea/scratch/repl/KtScratchReplExecutor.kt index 6d27c438df9..68b4426bf12 100644 --- a/idea/idea-jvm/src/org/jetbrains/kotlin/idea/scratch/repl/KtScratchReplExecutor.kt +++ b/idea/idea-jvm/src/org/jetbrains/kotlin/idea/scratch/repl/KtScratchReplExecutor.kt @@ -40,7 +40,7 @@ class KtScratchReplExecutor(file: ScratchFile) : ScratchExecutor(file) { private lateinit var osProcessHandler: OSProcessHandler override fun execute() { - handlers.forEach { it.onStart(file) } + handler.onStart(file) val module = file.getModule() ?: return error("Module should be selected") val cmdLine = KotlinConsoleKeeper.createCommandLine(module) @@ -62,7 +62,7 @@ class KtScratchReplExecutor(file: ScratchFile) : ScratchExecutor(file) { try { osProcessHandler.process.destroy() } finally { - handlers.forEach { it.onFinish(file) } + handler.onFinish(file) } } @@ -80,8 +80,8 @@ class KtScratchReplExecutor(file: ScratchFile) : ScratchExecutor(file) { } private fun error(file: ScratchFile, message: String) { - handlers.forEach { it.error(file, message) } - handlers.forEach { it.onFinish(file) } + handler.error(file, message) + handler.onFinish(file) } private class ReplHistory { @@ -118,7 +118,7 @@ class KtScratchReplExecutor(file: ScratchFile) : ScratchExecutor(file) { } override fun notifyProcessTerminated(exitCode: Int) { - handlers.forEach { it.onFinish(file) } + handler.onFinish(file) } private fun strToSource(s: String, encoding: Charset = Charsets.UTF_8) = InputSource(ByteArrayInputStream(s.toByteArray(encoding))) @@ -128,8 +128,7 @@ class KtScratchReplExecutor(file: ScratchFile) : ScratchExecutor(file) { val output = try { factory.newDocumentBuilder().parse(strToSource(text)) } catch (e: Exception) { - handlers.forEach { it.error(file, "Couldn't parse REPL output: $text") } - return + return handler.error(file, "Couldn't parse REPL output: $text") } val root = output.firstChild as Element @@ -152,7 +151,7 @@ class KtScratchReplExecutor(file: ScratchFile) : ScratchExecutor(file) { } if (lastExpression != null) { - handlers.forEach { it.handle(file, lastExpression, result) } + handler.handle(file, lastExpression, result) } } }