From 9a6dec0dbdae552c0ae1d612ea89abf4581b07d0 Mon Sep 17 00:00:00 2001 From: Skylot Date: Mon, 14 Nov 2022 12:09:07 +0000 Subject: [PATCH] fix: scripts runtime code and docs clean up --- jadx-gui/build.gradle | 6 +- .../main/java/jadx/gui/logs/LogAppender.java | 2 +- .../main/java/jadx/gui/logs/LogOptions.java | 2 +- .../script/ScriptCompleteProvider.java | 9 +- .../plugins/script/ScriptContentPanel.java | 8 +- jadx-plugins/jadx-script/README.md | 19 ++-- .../jadx-script/examples/build.gradle.kts | 4 +- .../jadx-script-ide/build.gradle.kts | 10 +- .../{ScriptCompiler.kt => ScriptServices.kt} | 4 +- .../jadx-script-plugin/build.gradle.kts | 8 +- .../jadx/plugins/script/JadxScriptPlugin.kt | 7 +- .../kotlin/jadx/plugins/script/ScriptEval.kt | 91 +++++++++++++++++++ .../script/passes/JadxScriptAfterLoadPass.kt | 13 +-- .../jadx/plugins/script/runner/ScriptEval.kt | 78 ---------------- .../plugins/script/runner/ScriptStates.kt | 20 ---- .../script/runtime/JadxScriptTemplate.kt | 11 +-- .../runtime/{Runtime.kt => ScriptRuntime.kt} | 9 +- 17 files changed, 146 insertions(+), 155 deletions(-) rename jadx-plugins/jadx-script/jadx-script-ide/src/main/kotlin/{ScriptCompiler.kt => ScriptServices.kt} (95%) create mode 100644 jadx-plugins/jadx-script/jadx-script-plugin/src/main/kotlin/jadx/plugins/script/ScriptEval.kt delete mode 100644 jadx-plugins/jadx-script/jadx-script-plugin/src/main/kotlin/jadx/plugins/script/runner/ScriptEval.kt rename jadx-plugins/jadx-script/jadx-script-runtime/src/main/kotlin/jadx/plugins/script/runtime/{Runtime.kt => ScriptRuntime.kt} (90%) diff --git a/jadx-gui/build.gradle b/jadx-gui/build.gradle index 8f842861d..52cc7873d 100644 --- a/jadx-gui/build.gradle +++ b/jadx-gui/build.gradle @@ -7,14 +7,14 @@ plugins { dependencies { implementation(project(':jadx-core')) - implementation(project(":jadx-cli")) + implementation(project(':jadx-cli')) // import mappings implementation project(':jadx-plugins:jadx-rename-mappings') // jadx-script autocomplete support - implementation(project(":jadx-plugins::jadx-script:jadx-script-ide")) - implementation(project(":jadx-plugins::jadx-script:jadx-script-runtime")) + implementation(project(':jadx-plugins:jadx-script:jadx-script-ide')) + implementation(project(':jadx-plugins:jadx-script:jadx-script-runtime')) implementation 'org.jetbrains.kotlin:kotlin-scripting-common:1.8.10' implementation 'com.fifesoft:autocomplete:3.3.1' diff --git a/jadx-gui/src/main/java/jadx/gui/logs/LogAppender.java b/jadx-gui/src/main/java/jadx/gui/logs/LogAppender.java index b981378ab..3ad7076c0 100644 --- a/jadx-gui/src/main/java/jadx/gui/logs/LogAppender.java +++ b/jadx-gui/src/main/java/jadx/gui/logs/LogAppender.java @@ -6,7 +6,7 @@ import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea; import jadx.core.utils.exceptions.JadxRuntimeException; import jadx.gui.utils.UiUtils; -import static jadx.plugins.script.runtime.JadxScriptTemplateKt.JADX_SCRIPT_LOG_PREFIX; +import static jadx.plugins.script.runtime.ScriptRuntime.JADX_SCRIPT_LOG_PREFIX; class LogAppender implements ILogListener { private final LogOptions options; diff --git a/jadx-gui/src/main/java/jadx/gui/logs/LogOptions.java b/jadx-gui/src/main/java/jadx/gui/logs/LogOptions.java index 01c570b37..c14736532 100644 --- a/jadx-gui/src/main/java/jadx/gui/logs/LogOptions.java +++ b/jadx-gui/src/main/java/jadx/gui/logs/LogOptions.java @@ -6,7 +6,7 @@ import ch.qos.logback.classic.Level; import jadx.core.utils.Utils; -import static jadx.plugins.script.runtime.JadxScriptTemplateKt.JADX_SCRIPT_LOG_PREFIX; +import static jadx.plugins.script.runtime.ScriptRuntime.JADX_SCRIPT_LOG_PREFIX; public class LogOptions { diff --git a/jadx-gui/src/main/java/jadx/gui/plugins/script/ScriptCompleteProvider.java b/jadx-gui/src/main/java/jadx/gui/plugins/script/ScriptCompleteProvider.java index 34c898ee3..df260bd22 100644 --- a/jadx-gui/src/main/java/jadx/gui/plugins/script/ScriptCompleteProvider.java +++ b/jadx-gui/src/main/java/jadx/gui/plugins/script/ScriptCompleteProvider.java @@ -27,10 +27,10 @@ import jadx.core.utils.ListUtils; import jadx.core.utils.exceptions.JadxRuntimeException; import jadx.gui.ui.codearea.AbstractCodeArea; import jadx.gui.utils.Icons; -import jadx.plugins.script.ide.ScriptCompiler; import jadx.plugins.script.ide.ScriptCompletionResult; +import jadx.plugins.script.ide.ScriptServices; -import static jadx.plugins.script.ide.ScriptCompilerKt.AUTO_COMPLETE_INSERT_STR; +import static jadx.plugins.script.ide.ScriptServicesKt.AUTO_COMPLETE_INSERT_STR; public class ScriptCompleteProvider extends CompletionProviderBase { private static final Logger LOG = LoggerFactory.getLogger(ScriptCompleteProvider.class); @@ -49,11 +49,10 @@ public class ScriptCompleteProvider extends CompletionProviderBase { } private final AbstractCodeArea codeArea; - private ScriptCompiler scriptComplete; + private ScriptServices scriptComplete; public ScriptCompleteProvider(AbstractCodeArea codeArea) { this.codeArea = codeArea; - // this.scriptComplete = new ScriptCompiler(codeArea.getNode().getName()); } private List getCompletions() { @@ -61,7 +60,7 @@ public class ScriptCompleteProvider extends CompletionProviderBase { String code = codeArea.getText(); int caretPos = codeArea.getCaretPosition(); // TODO: resolve error after reusing ScriptCompiler - scriptComplete = new ScriptCompiler(codeArea.getNode().getName()); + scriptComplete = new ScriptServices(codeArea.getNode().getName()); ScriptCompletionResult result = scriptComplete.complete(code, caretPos); int replacePos = getReplacePos(caretPos, result); if (!result.getReports().isEmpty()) { diff --git a/jadx-gui/src/main/java/jadx/gui/plugins/script/ScriptContentPanel.java b/jadx-gui/src/main/java/jadx/gui/plugins/script/ScriptContentPanel.java index c3b94923a..7a20da490 100644 --- a/jadx-gui/src/main/java/jadx/gui/plugins/script/ScriptContentPanel.java +++ b/jadx-gui/src/main/java/jadx/gui/plugins/script/ScriptContentPanel.java @@ -40,9 +40,9 @@ import jadx.gui.utils.UiUtils; import jadx.gui.utils.ui.ActionHandler; import jadx.gui.utils.ui.NodeLabel; import jadx.plugins.script.ide.ScriptAnalyzeResult; -import jadx.plugins.script.ide.ScriptCompiler; +import jadx.plugins.script.ide.ScriptServices; -import static jadx.plugins.script.runtime.JadxScriptTemplateKt.JADX_SCRIPT_LOG_PREFIX; +import static jadx.plugins.script.runtime.ScriptRuntime.JADX_SCRIPT_LOG_PREFIX; public class ScriptContentPanel extends AbstractCodeContentPanel { private static final long serialVersionUID = 6575696321112417513L; @@ -154,8 +154,8 @@ public class ScriptContentPanel extends AbstractCodeContentPanel { String code = scriptArea.getText(); String fileName = scriptArea.getNode().getName(); - ScriptCompiler scriptCompiler = new ScriptCompiler(fileName); - ScriptAnalyzeResult result = scriptCompiler.analyze(code, scriptArea.getCaretPosition()); + ScriptServices scriptServices = new ScriptServices(fileName); + ScriptAnalyzeResult result = scriptServices.analyze(code, scriptArea.getCaretPosition()); List issues = result.getIssues(); boolean success = true; for (ScriptDiagnostic issue : issues) { diff --git a/jadx-plugins/jadx-script/README.md b/jadx-plugins/jadx-script/README.md index 12dfed8a7..7d1855d11 100644 --- a/jadx-plugins/jadx-script/README.md +++ b/jadx-plugins/jadx-script/README.md @@ -1,11 +1,10 @@ ## JADX scripting support -NOTE: work still in progress! +:exclamation: Work still in progress! Script API is not stable! ### Examples -Check script examples in [`examples/scripts/`](https://github.com/skylot/jadx/tree/master/jadx-plugins/jadx-script/examples/scripts) -(start with [`hello`](https://github.com/skylot/jadx/blob/master/jadx-plugins/jadx-script/examples/scripts/hello.jadx.kts)) +Check script examples in [`examples/scripts/`](https://github.com/skylot/jadx/tree/master/jadx-plugins/jadx-script/examples/scripts)(start with [`hello`](https://github.com/skylot/jadx/blob/master/jadx-plugins/jadx-script/examples/scripts/hello.jadx.kts)) ### Script usage @@ -15,16 +14,16 @@ Just add script file as input #### In jadx-gui -1. Add script file to the project +1. Add script file to the project (using `Add files` or `New script` by right-click menu on `Inputs/Scripts`) 2. Script will appear in `Inputs/Scripts` section -3. After script change you need to reload project (`Reload` button in toolbar or `F5`) -4. You can enable `Live reload` option in `File` menu to reload project automatically on scripts change +3. After script change, you can run it using `Run` button in script editor toolbar or reload whole project (`Reload` button in toolbar or `F5`). + Also, you can enable `Live reload` option in `File` menu to reload project automatically on scripts change ### Script development -Jadx-gui for now don't support ~~autocompletion,~~ errors highlighting, docs and code navigation, -so best approach for script editing is to open jadx project in IntelliJ Idea and write your script in `examples/scripts/` folder. -Also, this will allow to debug your scripts: for that you need to create run configuration for jadx-cli or jadx-gui +Jadx-gui for now don't support ~~autocompletion~~, ~~errors highlighting~~, code navigation and docs, +so the best approach for script editing is to open jadx project in IntelliJ IDEA and write your script in `examples/scripts/` folder. +Also, this allows to debug your scripts: for that you need to create run configuration for jadx-cli or jadx-gui add breakpoints and next run it in debug mode (jadx-gui is preferred because of faster script reload). -Script logs and compilation errors will appear in `Log viewer` (separate script log will be added later) +Script logs and compilation errors will appear in `Log viewer` (try filter for show only script related logs) diff --git a/jadx-plugins/jadx-script/examples/build.gradle.kts b/jadx-plugins/jadx-script/examples/build.gradle.kts index 702b119d2..287fbd97a 100644 --- a/jadx-plugins/jadx-script/examples/build.gradle.kts +++ b/jadx-plugins/jadx-script/examples/build.gradle.kts @@ -1,8 +1,8 @@ dependencies { implementation(project(":jadx-plugins:jadx-script:jadx-script-runtime")) - implementation("org.jetbrains.kotlin:kotlin-stdlib-common") - implementation("org.jetbrains.kotlin:kotlin-script-runtime") + implementation(kotlin("stdlib-common")) + implementation(kotlin("script-runtime")) implementation("io.github.microutils:kotlin-logging-jvm:3.0.5") diff --git a/jadx-plugins/jadx-script/jadx-script-ide/build.gradle.kts b/jadx-plugins/jadx-script/jadx-script-ide/build.gradle.kts index 0fe08c978..f3be6a384 100644 --- a/jadx-plugins/jadx-script/jadx-script-ide/build.gradle.kts +++ b/jadx-plugins/jadx-script/jadx-script-ide/build.gradle.kts @@ -1,12 +1,12 @@ dependencies { - implementation("org.jetbrains.kotlin:kotlin-scripting-common") - implementation("org.jetbrains.kotlin:kotlin-scripting-jvm") - implementation("org.jetbrains.kotlin:kotlin-scripting-compiler-embeddable") - implementation("org.jetbrains.kotlin:kotlin-scripting-ide-services") - implementation(project(":jadx-plugins:jadx-script:jadx-script-runtime")) implementation(project(":jadx-plugins:jadx-script:jadx-script-plugin")) + implementation(kotlin("scripting-common")) + implementation(kotlin("scripting-jvm")) + implementation(kotlin("scripting-compiler-embeddable")) + implementation(kotlin("scripting-ide-services")) + implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4") implementation("io.github.microutils:kotlin-logging-jvm:3.0.5") } diff --git a/jadx-plugins/jadx-script/jadx-script-ide/src/main/kotlin/ScriptCompiler.kt b/jadx-plugins/jadx-script/jadx-script-ide/src/main/kotlin/ScriptServices.kt similarity index 95% rename from jadx-plugins/jadx-script/jadx-script-ide/src/main/kotlin/ScriptCompiler.kt rename to jadx-plugins/jadx-script/jadx-script-ide/src/main/kotlin/ScriptServices.kt index 16dbcfe06..c9f1e5ef0 100644 --- a/jadx-plugins/jadx-script/jadx-script-ide/src/main/kotlin/ScriptCompiler.kt +++ b/jadx-plugins/jadx-script/jadx-script-ide/src/main/kotlin/ScriptServices.kt @@ -1,6 +1,6 @@ package jadx.plugins.script.ide -import jadx.plugins.script.runner.ScriptEval +import jadx.plugins.script.ScriptEval import kotlinx.coroutines.runBlocking import org.jetbrains.kotlin.scripting.ide_services.compiler.KJvmReplCompilerWithIdeServices import kotlin.script.experimental.api.ReplAnalyzerResult @@ -28,7 +28,7 @@ data class ScriptAnalyzeResult( val reports: List, ) -class ScriptCompiler(private val scriptName: String) { +class ScriptServices(private val scriptName: String) { private val replCompiler = KJvmReplCompilerWithIdeServices() private val compileConf = ScriptEval().buildCompileConf() diff --git a/jadx-plugins/jadx-script/jadx-script-plugin/build.gradle.kts b/jadx-plugins/jadx-script/jadx-script-plugin/build.gradle.kts index b36108bd7..e0dac26f0 100644 --- a/jadx-plugins/jadx-script/jadx-script-plugin/build.gradle.kts +++ b/jadx-plugins/jadx-script/jadx-script-plugin/build.gradle.kts @@ -5,11 +5,9 @@ plugins { dependencies { implementation(project(":jadx-plugins:jadx-script:jadx-script-runtime")) - implementation("org.jetbrains.kotlin:kotlin-scripting-common") - implementation("org.jetbrains.kotlin:kotlin-scripting-jvm") - implementation("org.jetbrains.kotlin:kotlin-scripting-jvm-host") - - implementation(project(":jadx-plugins:jadx-script:jadx-script-runtime")) + implementation(kotlin("scripting-common")) + implementation(kotlin("scripting-jvm")) + implementation(kotlin("scripting-jvm-host")) implementation("io.github.microutils:kotlin-logging-jvm:3.0.5") } diff --git a/jadx-plugins/jadx-script/jadx-script-plugin/src/main/kotlin/jadx/plugins/script/JadxScriptPlugin.kt b/jadx-plugins/jadx-script/jadx-script-plugin/src/main/kotlin/jadx/plugins/script/JadxScriptPlugin.kt index 2775edd70..cd1a0178e 100644 --- a/jadx-plugins/jadx-script/jadx-script-plugin/src/main/kotlin/jadx/plugins/script/JadxScriptPlugin.kt +++ b/jadx-plugins/jadx-script/jadx-script-plugin/src/main/kotlin/jadx/plugins/script/JadxScriptPlugin.kt @@ -4,7 +4,6 @@ import jadx.api.plugins.JadxPlugin import jadx.api.plugins.JadxPluginContext import jadx.api.plugins.JadxPluginInfo import jadx.plugins.script.passes.JadxScriptAfterLoadPass -import jadx.plugins.script.runner.ScriptEval import jadx.plugins.script.runtime.data.JadxScriptAllOptions class JadxScriptPlugin : JadxPlugin { @@ -14,7 +13,9 @@ class JadxScriptPlugin : JadxPlugin { override fun init(init: JadxPluginContext) { init.registerOptions(scriptOptions) - val scriptStates = ScriptEval().process(init, scriptOptions) ?: return - init.addPass(JadxScriptAfterLoadPass(scriptStates)) + val scripts = ScriptEval().process(init, scriptOptions) + if (scripts.isNotEmpty()) { + init.addPass(JadxScriptAfterLoadPass(scripts)) + } } } diff --git a/jadx-plugins/jadx-script/jadx-script-plugin/src/main/kotlin/jadx/plugins/script/ScriptEval.kt b/jadx-plugins/jadx-script/jadx-script-plugin/src/main/kotlin/jadx/plugins/script/ScriptEval.kt new file mode 100644 index 000000000..a95b4f706 --- /dev/null +++ b/jadx-plugins/jadx-script/jadx-script-plugin/src/main/kotlin/jadx/plugins/script/ScriptEval.kt @@ -0,0 +1,91 @@ +package jadx.plugins.script + +import jadx.api.JadxDecompiler +import jadx.api.plugins.JadxPluginContext +import jadx.plugins.script.runtime.JadxScriptData +import jadx.plugins.script.runtime.JadxScriptTemplate +import jadx.plugins.script.runtime.data.JadxScriptAllOptions +import kotlin.script.experimental.api.EvaluationResult +import kotlin.script.experimental.api.ResultValue +import kotlin.script.experimental.api.ResultWithDiagnostics +import kotlin.script.experimental.api.ScriptCompilationConfiguration +import kotlin.script.experimental.api.ScriptDiagnostic.Severity +import kotlin.script.experimental.api.ScriptEvaluationConfiguration +import kotlin.script.experimental.api.compilerOptions +import kotlin.script.experimental.api.constructorArgs +import kotlin.script.experimental.host.toScriptSource +import kotlin.script.experimental.jvmhost.BasicJvmScriptingHost +import kotlin.script.experimental.jvmhost.createJvmCompilationConfigurationFromTemplate +import kotlin.script.experimental.jvmhost.createJvmEvaluationConfigurationFromTemplate +import kotlin.system.measureTimeMillis + +class ScriptEval { + + private val scriptingHost = BasicJvmScriptingHost() + + fun process(init: JadxPluginContext, scriptOptions: JadxScriptAllOptions): List { + val jadx = init.decompiler as JadxDecompiler + val scripts = jadx.args.inputFiles.filter { f -> f.name.endsWith(".jadx.kts") } + if (scripts.isEmpty()) { + return emptyList() + } + val scriptDataList = mutableListOf() + for (scriptFile in scripts) { + val scriptData = JadxScriptData(jadx, init, scriptOptions, scriptFile) + scriptDataList.add(scriptData) + eval(scriptData) + } + return scriptDataList + } + + fun buildCompileConf(): ScriptCompilationConfiguration { + return createJvmCompilationConfigurationFromTemplate() { + compilerOptions(listOf("-Xuse-k2")) + } + } + + fun buildEvalConf(scriptData: JadxScriptData): ScriptEvaluationConfiguration { + return createJvmEvaluationConfigurationFromTemplate { + constructorArgs(scriptData) + } + } + + private fun eval(scriptData: JadxScriptData) { + scriptData.log.debug { "Loading script: ${scriptData.scriptFile.absolutePath}" } + val execTime = measureTimeMillis { + val compilationConf = buildCompileConf() + val evalConf = buildEvalConf(scriptData) + val result = scriptingHost.eval(scriptData.scriptFile.toScriptSource(), compilationConf, evalConf) + processEvalResult(result, scriptData) + } + scriptData.log.debug { "Script '${scriptData.scriptName}' executed in $execTime ms" } + } + + private fun processEvalResult(res: ResultWithDiagnostics, scriptData: JadxScriptData) { + val log = scriptData.log + for (r in res.reports) { + val msg = r.render(withSeverity = false) + when (r.severity) { + Severity.FATAL, Severity.ERROR -> log.error(r.exception) { "Script execution error: $msg" } + Severity.WARNING -> log.warn { "Script execution issue: $msg" } + Severity.INFO -> log.info { "Script report: $msg" } + Severity.DEBUG -> log.debug { "Script report: $msg" } + } + } + when (res) { + is ResultWithDiagnostics.Success -> { + when (val retVal = res.value.returnValue) { + is ResultValue.Error -> log.error(retVal.error) { "Script execution error:" } + is ResultValue.Value -> log.info { "Script execution result: $retVal" } + is ResultValue.Unit -> {} + ResultValue.NotEvaluated -> {} + } + } + + is ResultWithDiagnostics.Failure -> { + scriptData.error = true + log.error { "Script execution failed: ${scriptData.scriptName}" } + } + } + } +} diff --git a/jadx-plugins/jadx-script/jadx-script-plugin/src/main/kotlin/jadx/plugins/script/passes/JadxScriptAfterLoadPass.kt b/jadx-plugins/jadx-script/jadx-script-plugin/src/main/kotlin/jadx/plugins/script/passes/JadxScriptAfterLoadPass.kt index ffcdd3dd6..582b8f66e 100644 --- a/jadx-plugins/jadx-script/jadx-script-plugin/src/main/kotlin/jadx/plugins/script/passes/JadxScriptAfterLoadPass.kt +++ b/jadx-plugins/jadx-script/jadx-script-plugin/src/main/kotlin/jadx/plugins/script/passes/JadxScriptAfterLoadPass.kt @@ -3,27 +3,24 @@ package jadx.plugins.script.passes import jadx.api.JadxDecompiler import jadx.api.plugins.pass.impl.SimpleJadxPassInfo import jadx.api.plugins.pass.types.JadxAfterLoadPass -import jadx.plugins.script.runner.ScriptStates -import mu.KotlinLogging +import jadx.plugins.script.runtime.JadxScriptData -private val LOG = KotlinLogging.logger {} - -class JadxScriptAfterLoadPass(private val scriptStates: ScriptStates) : JadxAfterLoadPass { +class JadxScriptAfterLoadPass(private val scripts: List) : JadxAfterLoadPass { override fun getInfo() = SimpleJadxPassInfo("JadxScriptAfterLoad", "Execute scripts 'afterLoad' block") override fun init(decompiler: JadxDecompiler) { - for (script in scriptStates.getScripts()) { + for (script in scripts) { if (script.error) { continue } try { - for (b in script.scriptData.afterLoad) { + for (b in script.afterLoad) { b.invoke() } } catch (e: Throwable) { script.error = true - LOG.error(e) { "Error executing 'afterLoad' block in script: ${script.scriptFile.name}" } + script.log.error(e) { "Error executing 'afterLoad' block in script: ${script.scriptFile.name}" } } } } diff --git a/jadx-plugins/jadx-script/jadx-script-plugin/src/main/kotlin/jadx/plugins/script/runner/ScriptEval.kt b/jadx-plugins/jadx-script/jadx-script-plugin/src/main/kotlin/jadx/plugins/script/runner/ScriptEval.kt deleted file mode 100644 index 4f134eac4..000000000 --- a/jadx-plugins/jadx-script/jadx-script-plugin/src/main/kotlin/jadx/plugins/script/runner/ScriptEval.kt +++ /dev/null @@ -1,78 +0,0 @@ -package jadx.plugins.script.runner - -import jadx.api.JadxDecompiler -import jadx.api.plugins.JadxPluginContext -import jadx.plugins.script.runtime.JadxScriptData -import jadx.plugins.script.runtime.JadxScriptTemplate -import jadx.plugins.script.runtime.data.JadxScriptAllOptions -import mu.KotlinLogging -import java.io.File -import kotlin.script.experimental.api.EvaluationResult -import kotlin.script.experimental.api.ResultValue -import kotlin.script.experimental.api.ResultWithDiagnostics -import kotlin.script.experimental.api.ScriptDiagnostic -import kotlin.script.experimental.api.ScriptEvaluationConfiguration -import kotlin.script.experimental.api.constructorArgs -import kotlin.script.experimental.host.toScriptSource -import kotlin.script.experimental.jvmhost.BasicJvmScriptingHost -import kotlin.script.experimental.jvmhost.createJvmCompilationConfigurationFromTemplate -import kotlin.script.experimental.jvmhost.createJvmEvaluationConfigurationFromTemplate - -private val LOG = KotlinLogging.logger {} - -class ScriptEval { - - fun process(init: JadxPluginContext, scriptOptions: JadxScriptAllOptions): ScriptStates? { - val jadx = init.decompiler as JadxDecompiler - val scripts = jadx.args.inputFiles.filter { f -> f.name.endsWith(".jadx.kts") } - if (scripts.isEmpty()) { - return null - } - val scriptStates = ScriptStates() - for (scriptFile in scripts) { - val scriptData = JadxScriptData(jadx, init, scriptOptions, scriptFile) - load(scriptFile, scriptData) - scriptStates.add(scriptFile, scriptData) - } - return scriptStates - } - - private fun load(scriptFile: File, scriptData: JadxScriptData) { - LOG.debug { "Loading script: ${scriptFile.absolutePath}" } - val result = eval(scriptFile, scriptData) - processEvalResult(result, scriptFile) - } - - fun buildCompileConf() = createJvmCompilationConfigurationFromTemplate() - - fun buildEvalConf(scriptData: JadxScriptData): ScriptEvaluationConfiguration { - return createJvmEvaluationConfigurationFromTemplate { - constructorArgs(scriptData) - } - } - - private fun eval(scriptFile: File, scriptData: JadxScriptData): ResultWithDiagnostics { - val compilationConf = buildCompileConf() - val evalConf = buildEvalConf(scriptData) - return BasicJvmScriptingHost().eval(scriptFile.toScriptSource(), compilationConf, evalConf) - } - - private fun processEvalResult(res: ResultWithDiagnostics, scriptFile: File) { - when (res) { - is ResultWithDiagnostics.Success -> { - val result = res.value.returnValue - if (result is ResultValue.Error) { - result.error.printStackTrace() - } - } - is ResultWithDiagnostics.Failure -> { - LOG.error { "Script execution failed: ${scriptFile.name}" } - res.reports - .filter { it.severity >= ScriptDiagnostic.Severity.ERROR } - .forEach { r -> - LOG.error(r.exception) { r.render(withSeverity = false) } - } - } - } - } -} diff --git a/jadx-plugins/jadx-script/jadx-script-plugin/src/main/kotlin/jadx/plugins/script/runner/ScriptStates.kt b/jadx-plugins/jadx-script/jadx-script-plugin/src/main/kotlin/jadx/plugins/script/runner/ScriptStates.kt index 6b03ea539..8b1378917 100644 --- a/jadx-plugins/jadx-script/jadx-script-plugin/src/main/kotlin/jadx/plugins/script/runner/ScriptStates.kt +++ b/jadx-plugins/jadx-script/jadx-script-plugin/src/main/kotlin/jadx/plugins/script/runner/ScriptStates.kt @@ -1,21 +1 @@ -package jadx.plugins.script.runner -import jadx.plugins.script.runtime.JadxScriptData -import java.io.File - -data class ScriptStateData( - val scriptFile: File, - val scriptData: JadxScriptData, - var error: Boolean = false, -) - -class ScriptStates { - - private val data: MutableList = ArrayList() - - fun add(scriptFile: File, scriptData: JadxScriptData) { - data.add(ScriptStateData(scriptFile, scriptData)) - } - - fun getScripts() = data -} diff --git a/jadx-plugins/jadx-script/jadx-script-runtime/src/main/kotlin/jadx/plugins/script/runtime/JadxScriptTemplate.kt b/jadx-plugins/jadx-script/jadx-script-runtime/src/main/kotlin/jadx/plugins/script/runtime/JadxScriptTemplate.kt index 82b902b6d..2ca8ba297 100644 --- a/jadx-plugins/jadx-script/jadx-script-runtime/src/main/kotlin/jadx/plugins/script/runtime/JadxScriptTemplate.kt +++ b/jadx-plugins/jadx-script/jadx-script-runtime/src/main/kotlin/jadx/plugins/script/runtime/JadxScriptTemplate.kt @@ -1,7 +1,6 @@ package jadx.plugins.script.runtime import kotlinx.coroutines.runBlocking -import mu.KotlinLogging import kotlin.script.experimental.annotations.KotlinScript import kotlin.script.experimental.api.ResultWithDiagnostics import kotlin.script.experimental.api.ScriptAcceptedLocation @@ -28,19 +27,19 @@ import kotlin.script.experimental.jvm.JvmDependency import kotlin.script.experimental.jvm.dependenciesFromCurrentContext import kotlin.script.experimental.jvm.jvm -const val JADX_SCRIPT_LOG_PREFIX = "JadxScript:" - @KotlinScript( fileExtension = "jadx.kts", compilationConfiguration = JadxScriptConfiguration::class, ) abstract class JadxScriptTemplate( - private val scriptData: JadxScriptData, + scriptData: JadxScriptData, ) { val scriptName = scriptData.scriptName - val log = KotlinLogging.logger("$JADX_SCRIPT_LOG_PREFIX$scriptName") + val log = scriptData.log - fun getJadxInstance() = JadxScriptInstance(scriptData, log) + private val scriptInstance = JadxScriptInstance(scriptData, log) + + fun getJadxInstance() = scriptInstance fun println(message: Any?) { log.info(message?.toString()) diff --git a/jadx-plugins/jadx-script/jadx-script-runtime/src/main/kotlin/jadx/plugins/script/runtime/Runtime.kt b/jadx-plugins/jadx-script/jadx-script-runtime/src/main/kotlin/jadx/plugins/script/runtime/ScriptRuntime.kt similarity index 90% rename from jadx-plugins/jadx-script/jadx-script-runtime/src/main/kotlin/jadx/plugins/script/runtime/Runtime.kt rename to jadx-plugins/jadx-script/jadx-script-runtime/src/main/kotlin/jadx/plugins/script/runtime/ScriptRuntime.kt index 63942720e..51494e17c 100644 --- a/jadx-plugins/jadx-script/jadx-script-runtime/src/main/kotlin/jadx/plugins/script/runtime/Runtime.kt +++ b/jadx-plugins/jadx-script/jadx-script-runtime/src/main/kotlin/jadx/plugins/script/runtime/ScriptRuntime.kt @@ -1,3 +1,4 @@ +@file:JvmName("ScriptRuntime") @file:Suppress("unused", "MemberVisibilityCanBePrivate") package jadx.plugins.script.runtime @@ -17,17 +18,21 @@ import jadx.plugins.script.runtime.data.Replace import jadx.plugins.script.runtime.data.Search import jadx.plugins.script.runtime.data.Stages import mu.KLogger +import mu.KotlinLogging import java.io.File +const val JADX_SCRIPT_LOG_PREFIX = "JadxScript:" + class JadxScriptData( val jadxInstance: JadxDecompiler, val pluginContext: JadxPluginContext, val options: JadxScriptAllOptions, val scriptFile: File, ) { - val afterLoad: MutableList<() -> Unit> = ArrayList() - val scriptName = scriptFile.name.removeSuffix(".jadx.kts") + val log = KotlinLogging.logger("$JADX_SCRIPT_LOG_PREFIX$scriptName") + val afterLoad: MutableList<() -> Unit> = ArrayList() + var error: Boolean = false } class JadxScriptInstance(