diff --git a/platform/testGuiFramework/src/com/intellij/testGuiFramework/recorder/actions/PerformScriptAction.kt b/platform/testGuiFramework/src/com/intellij/testGuiFramework/recorder/actions/PerformScriptAction.kt index ed24787a3f54..63788c261a30 100644 --- a/platform/testGuiFramework/src/com/intellij/testGuiFramework/recorder/actions/PerformScriptAction.kt +++ b/platform/testGuiFramework/src/com/intellij/testGuiFramework/recorder/actions/PerformScriptAction.kt @@ -22,7 +22,6 @@ import com.intellij.openapi.diagnostic.Logger import com.intellij.testGuiFramework.recorder.compile.KotlinCompileUtil import com.intellij.testGuiFramework.recorder.components.GuiRecorderComponent import com.intellij.testGuiFramework.recorder.ui.Notifier -import java.util.function.Consumer /** * @author Sergey Karashevich @@ -36,13 +35,9 @@ class PerformScriptAction : AnAction(null, "Run GUI Script", AllIcons.Actions.Ex override fun actionPerformed(p0: AnActionEvent?) { LOG.info("Compile and evaluate current script buffer") - Notifier.updateStatus("Compiling and performing current script") + Notifier.updateStatus("${Notifier.LONG_OPERATION_PREFIX}Compiling and performing current script") val editor = GuiRecorderComponent.getEditor() - //we wrapping it in lambda consumer because of different classloader problem in CompileDaemon class. - val myNotifier: Consumer = Consumer { statusMessage -> Notifier.updateStatus(statusMessage) } - -// ApplicationManager.getApplication().executeOnPooledThread { KotlinCompileUtil.compileAndEvalCodeWithNotifier(editor.document.text, myNotifier) } KotlinCompileUtil.compileAndRun(editor.document.text) } diff --git a/platform/testGuiFramework/src/com/intellij/testGuiFramework/recorder/actions/StopRecAction.kt b/platform/testGuiFramework/src/com/intellij/testGuiFramework/recorder/actions/StopRecAction.kt index 27debafc1133..8e5d5992c1b4 100644 --- a/platform/testGuiFramework/src/com/intellij/testGuiFramework/recorder/actions/StopRecAction.kt +++ b/platform/testGuiFramework/src/com/intellij/testGuiFramework/recorder/actions/StopRecAction.kt @@ -20,16 +20,18 @@ import com.intellij.openapi.actionSystem.AnAction import com.intellij.openapi.actionSystem.AnActionEvent import com.intellij.testGuiFramework.recorder.GlobalActionRecorder import com.intellij.testGuiFramework.recorder.ScriptGenerator +import com.intellij.testGuiFramework.recorder.components.GuiRecorderComponent import com.intellij.testGuiFramework.recorder.ui.Notifier /** * @author Sergey Karashevich */ -class StopRecAction : AnAction(null, "Stop Recording and Clear Buffer", AllIcons.Actions.Suspend) { +class StopRecAction : AnAction(null, "Stop Recording, Compiling, Running and Clear Buffer", AllIcons.Actions.Suspend) { override fun actionPerformed(p0: AnActionEvent?) { GlobalActionRecorder.deactivate() - Notifier.updateStatus("Recording stopped") + GuiRecorderComponent.cancelCurrentTask() + Notifier.updateStatus("Stopped") ScriptGenerator.clearScriptBuffer() } diff --git a/platform/testGuiFramework/src/com/intellij/testGuiFramework/recorder/compile/KotlinCompileUtil.kt b/platform/testGuiFramework/src/com/intellij/testGuiFramework/recorder/compile/KotlinCompileUtil.kt index d721990c525a..6a55fdcab38b 100644 --- a/platform/testGuiFramework/src/com/intellij/testGuiFramework/recorder/compile/KotlinCompileUtil.kt +++ b/platform/testGuiFramework/src/com/intellij/testGuiFramework/recorder/compile/KotlinCompileUtil.kt @@ -29,13 +29,15 @@ object KotlinCompileUtil { private val LOG by lazy { Logger.getInstance("#${KotlinCompileUtil::class.qualifiedName}") } + private val localCompiler: LocalCompiler by lazy {LocalCompiler()} + fun compile(codeString: String) { - LocalCompiler().compileOnPooledThread(ScriptGenerator.ScriptWrapper.wrapScript(codeString), + localCompiler.compileOnPooledThread(ScriptGenerator.ScriptWrapper.wrapScript(codeString), getAllUrls().map { Paths.get(it.toURI()).toFile().path }) } fun compileAndRun(codeString: String) { - LocalCompiler().compileAndRunOnPooledThread(ScriptGenerator.ScriptWrapper.wrapScript(codeString), + localCompiler.compileAndRunOnPooledThread(ScriptGenerator.ScriptWrapper.wrapScript(codeString), getAllUrls().map { Paths.get(it.toURI()).toFile().path }) } diff --git a/platform/testGuiFramework/src/com/intellij/testGuiFramework/recorder/compile/LocalCompiler.kt b/platform/testGuiFramework/src/com/intellij/testGuiFramework/recorder/compile/LocalCompiler.kt index 400cb63f8a8b..83f3c2e9fc90 100644 --- a/platform/testGuiFramework/src/com/intellij/testGuiFramework/recorder/compile/LocalCompiler.kt +++ b/platform/testGuiFramework/src/com/intellij/testGuiFramework/recorder/compile/LocalCompiler.kt @@ -43,6 +43,8 @@ class LocalCompiler { private val LOG by lazy { Logger.getInstance("#${LocalCompiler::class.qualifiedName}") } + var codeHash: Int? = null + val TEST_CLASS_NAME = "CurrentTest" val helloKtText = "fun main(args: Array) { \n println(\"Hello, World!\") \n }" @@ -63,20 +65,26 @@ class LocalCompiler { } fun compileAndRunOnPooledThread(code: String, classpath: List) { - ApplicationManager.getApplication().executeOnPooledThread({ - try { - compile(code, classpath) - run2() - } - catch (ce: CompilationException) { - LOG.error(ce.message) - } - }) + val taskFuture = ApplicationManager.getApplication().executeOnPooledThread({ + try { + if (codeHash == null || codeHash != code.hashCode()) { + compile(code, classpath) + codeHash = code.hashCode() + } + run2() + } + catch (ce: CompilationException) { + LOG.error(ce.message) + } + }) + GuiRecorderComponent.setCurrentTask(taskFuture) + } //alternative way to run compiled code with pluginClassloader built especially for this file private fun run2() { + Notifier.updateStatus("${Notifier.LONG_OPERATION_PREFIX}Script running...") val testUrl = tempDir.toURI().toURL() var classLoadersArray: Array try { @@ -93,7 +101,6 @@ class LocalCompiler { val testCase = currentTest.newInstance() val setUpMethod = currentTest.getMethod("setUp") val testMethod = currentTest.getMethod(ScriptGenerator.ScriptWrapper.TEST_METHOD_NAME) - Notifier.updateStatus("Script running...") GuiRecorderComponent.setState(GuiRecorderComponent.States.RUNNING) try { setUpMethod.invoke(testCase) @@ -127,7 +134,7 @@ class LocalCompiler { val testCase = currentTest.newInstance() val setUpMethod = currentTest.getMethod("setUp") val testMethod = currentTest.getMethod(ScriptGenerator.ScriptWrapper.TEST_METHOD_NAME) - Notifier.updateStatus("Script running...") + Notifier.updateStatus("${Notifier.LONG_OPERATION_PREFIX}Script running...") GuiRecorderComponent.setState(GuiRecorderComponent.States.RUNNING) try { setUpMethod.invoke(testCase) @@ -159,7 +166,7 @@ class LocalCompiler { val kotlinCompilerJar = getKotlinCompilerJar() val libDirLocation = getApplicationLibDir().parentFile - Notifier.updateStatus("Compiling...") + Notifier.updateStatus("${Notifier.LONG_OPERATION_PREFIX}Compiling...") GuiRecorderComponent.setState(GuiRecorderComponent.States.COMPILING) @@ -204,10 +211,10 @@ class LocalCompiler { private fun getPluginKotlincDir(): File { // if (ApplicationManager.getApplication().isUnitTestMode || (this.javaClass.classLoader.javaClass.name == "sun.misc.Launcher\$AppClassLoader")) { - val tempPath = PathManager.getTempPath() - val tempDirFile = File(tempPath) - FileUtil.ensureExists(tempDirFile) - return tempDirFile + val tempPath = PathManager.getTempPath() + val tempDirFile = File(tempPath) + FileUtil.ensureExists(tempDirFile) + return tempDirFile // } // // val pluginId = (this.javaClass.classLoader as PluginClassLoader).pluginId @@ -226,7 +233,7 @@ class LocalCompiler { fun downloadKotlinCompilerJar(destDirPath: String?): File { - Notifier.updateStatus("Downloading kotlin-compiler.jar...") + Notifier.updateStatus("${Notifier.LONG_OPERATION_PREFIX}Downloading kotlin-compiler.jar...") val downloader = DownloadableFileService.getInstance() val description = downloader.createFileDescription(kotlinCompilerJarUrl, kotlinCompilerJarName) ApplicationManager.getApplication().invokeAndWait({ diff --git a/platform/testGuiFramework/src/com/intellij/testGuiFramework/recorder/components/GuiRecorderComponent.kt b/platform/testGuiFramework/src/com/intellij/testGuiFramework/recorder/components/GuiRecorderComponent.kt index 64e5c296e4b5..a10f3353478f 100644 --- a/platform/testGuiFramework/src/com/intellij/testGuiFramework/recorder/components/GuiRecorderComponent.kt +++ b/platform/testGuiFramework/src/com/intellij/testGuiFramework/recorder/components/GuiRecorderComponent.kt @@ -18,6 +18,7 @@ package com.intellij.testGuiFramework.recorder.components import com.intellij.openapi.Disposable import com.intellij.openapi.components.ApplicationComponent import com.intellij.testGuiFramework.recorder.ui.GuiScriptEditorFrame +import java.util.concurrent.Future /** * @author Sergey Karashevich @@ -33,6 +34,8 @@ object GuiRecorderComponent : ApplicationComponent, Disposable { private var myFrame: GuiScriptEditorFrame? = null + private var currentTask: Future<*>? = null + override fun getComponentName() = "GuiRecorderComponent" override fun disposeComponent() { @@ -43,6 +46,12 @@ object GuiRecorderComponent : ApplicationComponent, Disposable { } + fun setCurrentTask(task: Future<*>) { currentTask = task } + + fun cancelCurrentTask() { + if (currentTask != null && !currentTask!!.isDone) currentTask!!.cancel(true) + } + fun getState() = myState fun setState(yaState: States) { diff --git a/platform/testGuiFramework/src/com/intellij/testGuiFramework/recorder/ui/Notifier.kt b/platform/testGuiFramework/src/com/intellij/testGuiFramework/recorder/ui/Notifier.kt index c4f75d20a39c..489d87b68504 100644 --- a/platform/testGuiFramework/src/com/intellij/testGuiFramework/recorder/ui/Notifier.kt +++ b/platform/testGuiFramework/src/com/intellij/testGuiFramework/recorder/ui/Notifier.kt @@ -16,7 +16,6 @@ package com.intellij.testGuiFramework.recorder.ui import com.intellij.testGuiFramework.recorder.components.GuiRecorderComponent -import com.intellij.util.ui.EdtInvocationManager import javax.swing.SwingUtilities /** @@ -24,21 +23,23 @@ import javax.swing.SwingUtilities */ object Notifier { + val LONG_OPERATION_PREFIX = "" + fun updateStatus(statusMessage: String) { + if (GuiRecorderComponent.getFrame() == null) return val guiScriptEditorPanel = GuiRecorderComponent.getFrame()!!.getGuiScriptEditorPanel() + val statusHandler: (String) -> Unit = { status -> - if (status.startsWith("")) { - guiScriptEditorPanel.updateStatusWithProgress(status.substring(6)) + if (status.startsWith(LONG_OPERATION_PREFIX)) { + guiScriptEditorPanel.updateStatusWithProgress(status.removePrefix(LONG_OPERATION_PREFIX)) } else { guiScriptEditorPanel.stopProgress() guiScriptEditorPanel.updateStatus(status) } } - - if (EdtInvocationManager.getInstance().isEventDispatchThread) statusHandler.invoke(statusMessage) - else SwingUtilities.invokeAndWait { statusHandler.invoke(statusMessage) } + SwingUtilities.invokeLater { statusHandler.invoke(statusMessage) } } } \ No newline at end of file