Refactoring: add composite output handler to avoid multiple forEach calls
This commit is contained in:
@@ -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<ScratchOutputHandler>()
|
||||
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<ScratchOutputHandler>()
|
||||
|
||||
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) }
|
||||
}
|
||||
}
|
||||
}
|
||||
+15
-19
@@ -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))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user