diff --git a/README.md b/README.md index abbaecb8c..2b38fe037 100644 --- a/README.md +++ b/README.md @@ -72,7 +72,7 @@ For Windows, you can download it from [oracle.com](https://www.oracle.com/java/t You can use jadx in your java projects, check details on [wiki page](https://github.com/skylot/jadx/wiki/Use-jadx-as-a-library) ### Build from source -JDK 11 or higher must be installed: +JDK 17 or higher must be installed: ``` git clone https://github.com/skylot/jadx.git cd jadx diff --git a/build.gradle.kts b/build.gradle.kts index df96f46c6..5ce176532 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -8,7 +8,7 @@ import java.util.Locale plugins { id("com.github.ben-manes.versions") version "0.53.0" id("se.patrikerdes.use-latest-versions") version "0.2.19" - id("com.diffplug.spotless") version "6.25.0" + id("com.diffplug.spotless") version "8.4.0" } val jadxVersion by extra { System.getenv("JADX_VERSION") ?: "dev" } @@ -98,7 +98,9 @@ val copyArtifacts by tasks.registering(Copy::class) { from(tasks.getByPath(":jadx-cli:installShadowDist")) { exclude("**/*.jar") filter { line -> - jarCliPattern.matcher(line).replaceAll("jadx-$1-all.jar") + jarCliPattern + .matcher(line) + .replaceAll("jadx-$1-all.jar") .replace("-jar \"\\\"\$CLASSPATH\\\"\"", "-cp \"\\\"\$CLASSPATH\\\"\" jadx.cli.JadxCLI") .replace("-jar \"%CLASSPATH%\"", "-cp \"%CLASSPATH%\" jadx.cli.JadxCLI") } diff --git a/buildSrc/src/main/kotlin/jadx-java.gradle.kts b/buildSrc/src/main/kotlin/jadx-java.gradle.kts index 0f60d3016..c44819d11 100644 --- a/buildSrc/src/main/kotlin/jadx-java.gradle.kts +++ b/buildSrc/src/main/kotlin/jadx-java.gradle.kts @@ -15,15 +15,15 @@ version = jadxVersion dependencies { implementation("org.slf4j:slf4j-api:2.0.17") - compileOnly("org.jetbrains:annotations:26.0.2") + compileOnly("org.jetbrains:annotations:26.1.0") - testImplementation("ch.qos.logback:logback-classic:1.5.22") - testImplementation("org.assertj:assertj-core:3.27.6") + testImplementation("ch.qos.logback:logback-classic:1.5.32") + testImplementation("org.assertj:assertj-core:3.27.7") testImplementation("org.junit.jupiter:junit-jupiter:5.13.3") testRuntimeOnly("org.junit.platform:junit-platform-launcher") - testCompileOnly("org.jetbrains:annotations:26.0.2") + testCompileOnly("org.jetbrains:annotations:26.1.0") } repositories { diff --git a/buildSrc/src/main/kotlin/jadx-rewrite.gradle.kts b/buildSrc/src/main/kotlin/jadx-rewrite.gradle.kts index ceca3fe5a..be37a39c9 100644 --- a/buildSrc/src/main/kotlin/jadx-rewrite.gradle.kts +++ b/buildSrc/src/main/kotlin/jadx-rewrite.gradle.kts @@ -7,10 +7,10 @@ repositories { } dependencies { - rewrite("org.openrewrite.recipe:rewrite-testing-frameworks:3.24.0") - rewrite("org.openrewrite.recipe:rewrite-logging-frameworks:3.20.0") - rewrite("org.openrewrite.recipe:rewrite-migrate-java:3.24.0") - rewrite("org.openrewrite.recipe:rewrite-static-analysis:2.24.0") + rewrite("org.openrewrite.recipe:rewrite-testing-frameworks:3.30.0") + rewrite("org.openrewrite.recipe:rewrite-logging-frameworks:3.26.0") + rewrite("org.openrewrite.recipe:rewrite-migrate-java:3.30.1") + rewrite("org.openrewrite.recipe:rewrite-static-analysis:2.30.1") } tasks { diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index f8e1ee312..d997cfc60 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 8a848873f..8e61ef125 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,7 +1,7 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionSha256Sum=72f44c9f8ebcb1af43838f45ee5c4aa9c5444898b3468ab3f4af7b6076c5bc3f -distributionUrl=https\://services.gradle.org/distributions/gradle-9.2.1-bin.zip +distributionSha256Sum=2ab2958f2a1e51120c326cad6f385153bb11ee93b3c216c5fccebfdfbb7ec6cb +distributionUrl=https\://services.gradle.org/distributions/gradle-9.4.1-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/gradlew b/gradlew index adff685a0..739907dfd 100755 --- a/gradlew +++ b/gradlew @@ -57,7 +57,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# https://github.com/gradle/gradle/blob/2d6327017519d23b96af35865dc997fcb544fb40/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. diff --git a/jadx-cli/build.gradle.kts b/jadx-cli/build.gradle.kts index 3354a5152..619e49731 100644 --- a/jadx-cli/build.gradle.kts +++ b/jadx-cli/build.gradle.kts @@ -25,7 +25,7 @@ dependencies { runtimeOnly(project(":jadx-plugins:jadx-apks-input")) implementation("org.jcommander:jcommander:2.0") - implementation("ch.qos.logback:logback-classic:1.5.22") + implementation("ch.qos.logback:logback-classic:1.5.32") implementation("com.google.code.gson:gson:2.13.2") } diff --git a/jadx-core/build.gradle.kts b/jadx-core/build.gradle.kts index 572f438ec..2e7334982 100644 --- a/jadx-core/build.gradle.kts +++ b/jadx-core/build.gradle.kts @@ -24,7 +24,7 @@ dependencies { strictly("[3.33, 3.34[") // from 3.34 compiled with Java 17 } } - testImplementation("tools.profiler:async-profiler:4.2") + testImplementation("tools.profiler:async-profiler:4.3") } val jadxTestJavaVersion = getTestJavaVersion() @@ -32,7 +32,10 @@ val jadxTestJavaVersion = getTestJavaVersion() fun getTestJavaVersion(): Int? { val envVarName = "JADX_TEST_JAVA_VERSION" val testJavaVer = System.getenv(envVarName)?.toInt() ?: return null - val currentJavaVer = java.toolchain.languageVersion.get().asInt() + val currentJavaVer = + java.toolchain.languageVersion + .get() + .asInt() if (testJavaVer < currentJavaVer) { throw GradleException("'$envVarName' can't be set to lower version than $currentJavaVer") } diff --git a/jadx-gui/build.gradle.kts b/jadx-gui/build.gradle.kts index 73cd322b2..a3d703c6e 100644 --- a/jadx-gui/build.gradle.kts +++ b/jadx-gui/build.gradle.kts @@ -55,7 +55,13 @@ dependencies { implementation("com.eclipsesource.j2v8:j2v8_linux_x86_64:4.6.0") implementation("com.eclipsesource.j2v8:j2v8_win32_x86_64:4.6.0") - testImplementation(project.project(":jadx-core").sourceSets.getByName("test").output) + testImplementation( + project + .project(":jadx-core") + .sourceSets + .getByName("test") + .output, + ) } val jadxVersion: String by rootProject.extra @@ -119,12 +125,14 @@ project.components.withType(AdhocComponentWithVariants::class.java).forEach { c tasks.startShadowScripts { doLast { val newWindowsScriptContent = - windowsScript.readText() + windowsScript + .readText() .replace("java.exe", "javaw.exe") .replace("\"%JAVA_EXE%\" %DEFAULT_JVM_OPTS%", "start \"jadx-gui\" /B \"%JAVA_EXE%\" %DEFAULT_JVM_OPTS%") // Add launch script path as a property val newUnixScriptContent = - unixScript.readText() + unixScript + .readText() .replace( Regex("DEFAULT_JVM_OPTS=.+", RegexOption.MULTILINE), { result -> result.value + "\" \\\"-Djadx.launchScript.path=\$(realpath $0)\\\"\"" }, @@ -151,18 +159,24 @@ launch4j { supportUrl.set("https://github.com/skylot/jadx") bundledJrePath.set(if (project.hasProperty("bundleJRE")) "%EXEDIR%/jre" else "%JAVA_HOME%") - classpath.set(tasks.getByName("shadowJar").outputs.files.map { "%EXEDIR%/lib/${it.name}" }.sorted().toList()) + classpath.set( + tasks + .getByName("shadowJar") + .outputs.files + .map { "%EXEDIR%/lib/${it.name}" } + .sorted() + .toList(), + ) println("Launch4J classpath: ${classpath.get()}") chdir.set("") // don't change current dir libraryDir.set("") // don't add any libs } -fun escapeJVMOptions(): List { - return application.applicationDefaultJvmArgs +fun escapeJVMOptions(): List = + application.applicationDefaultJvmArgs .toList() .map { if (it.startsWith("-D")) "\"$it\"" else it } -} runtime { addOptions("--strip-debug", "--no-header-files", "--no-man-pages") diff --git a/jadx-gui/src/main/java/jadx/gui/ui/action/XposedAction.kt b/jadx-gui/src/main/java/jadx/gui/ui/action/XposedAction.kt index 300545a78..a02ee7761 100644 --- a/jadx-gui/src/main/java/jadx/gui/ui/action/XposedAction.kt +++ b/jadx-gui/src/main/java/jadx/gui/ui/action/XposedAction.kt @@ -32,17 +32,13 @@ class XposedAction(codeArea: CodeArea) : JNodeAction(ActionModel.XPOSED_COPY, co } } - override fun isActionEnabled(node: JNode?): Boolean { - return node is JMethod || node is JClass || node is JField - } + override fun isActionEnabled(node: JNode?): Boolean = node is JMethod || node is JClass || node is JField - private fun generateXposedSnippet(node: JNode): String { - return when (node) { - is JMethod -> generateMethodSnippet(node) - is JClass -> generateClassSnippet(node) - is JField -> generateFieldSnippet(node) - else -> throw JadxRuntimeException("Unsupported node type: " + node.javaClass) - } + private fun generateXposedSnippet(node: JNode): String = when (node) { + is JMethod -> generateMethodSnippet(node) + is JClass -> generateClassSnippet(node) + is JField -> generateFieldSnippet(node) + else -> throw JadxRuntimeException("Unsupported node type: " + node.javaClass) } private fun generateMethodSnippet(jMethod: JMethod): String { @@ -73,6 +69,7 @@ class XposedAction(codeArea: CodeArea) : JNodeAction(ActionModel.XPOSED_COPY, co super.afterHookedMethod(param); } });""" + XposedCodegenLanguage.KOTLIN -> """XposedHelpers.%s("%s", classLoader, %s, object : XC_MethodHook() { override fun beforeHookedMethod(param: MethodHookParam) { @@ -88,29 +85,31 @@ class XposedAction(codeArea: CodeArea) : JNodeAction(ActionModel.XPOSED_COPY, co return String.format(template, xposedMethod, rawClassName, args.joinToString(", ")) } - private fun fixTypeContent(type: ArgType): String { - return when { - type.isGeneric -> "\"${type.`object`}\"" - type.isGenericType && type.isObject && type.isTypeKnown -> "java.lang.Object" - type.isPrimitive -> when (language) { - XposedCodegenLanguage.JAVA -> "$type.class" - XposedCodegenLanguage.KOTLIN -> when (type.primitiveType) { - PrimitiveType.BOOLEAN -> "Boolean::class.javaPrimitiveType" - PrimitiveType.CHAR -> "Char::class.javaPrimitiveType" - PrimitiveType.BYTE -> "Byte::class.javaPrimitiveType" - PrimitiveType.SHORT -> "Short::class.javaPrimitiveType" - PrimitiveType.INT -> "Int::class.javaPrimitiveType" - PrimitiveType.FLOAT -> "Float::class.javaPrimitiveType" - PrimitiveType.LONG -> "Long::class.javaPrimitiveType" - PrimitiveType.DOUBLE -> "Double::class.javaPrimitiveType" - PrimitiveType.OBJECT -> "Any::class.java" - PrimitiveType.ARRAY -> "Array::class.java" - PrimitiveType.VOID -> "Void::class.javaPrimitiveType" - else -> throw JadxRuntimeException("Unknown or null primitive type: $type") - } + private fun fixTypeContent(type: ArgType): String = when { + type.isGeneric -> "\"${type.`object`}\"" + + type.isGenericType && type.isObject && type.isTypeKnown -> "java.lang.Object" + + type.isPrimitive -> when (language) { + XposedCodegenLanguage.JAVA -> "$type.class" + + XposedCodegenLanguage.KOTLIN -> when (type.primitiveType) { + PrimitiveType.BOOLEAN -> "Boolean::class.javaPrimitiveType" + PrimitiveType.CHAR -> "Char::class.javaPrimitiveType" + PrimitiveType.BYTE -> "Byte::class.javaPrimitiveType" + PrimitiveType.SHORT -> "Short::class.javaPrimitiveType" + PrimitiveType.INT -> "Int::class.javaPrimitiveType" + PrimitiveType.FLOAT -> "Float::class.javaPrimitiveType" + PrimitiveType.LONG -> "Long::class.javaPrimitiveType" + PrimitiveType.DOUBLE -> "Double::class.javaPrimitiveType" + PrimitiveType.OBJECT -> "Any::class.java" + PrimitiveType.ARRAY -> "Array::class.java" + PrimitiveType.VOID -> "Void::class.javaPrimitiveType" + else -> throw JadxRuntimeException("Unknown or null primitive type: $type") } - else -> "\"$type\"" } + + else -> "\"$type\"" } private fun generateClassSnippet(jClass: JClass): String { diff --git a/jadx-plugins-tools/build.gradle.kts b/jadx-plugins-tools/build.gradle.kts index d0fd158d1..cba8fbb87 100644 --- a/jadx-plugins-tools/build.gradle.kts +++ b/jadx-plugins-tools/build.gradle.kts @@ -11,5 +11,5 @@ dependencies { implementation("com.google.code.gson:gson:2.13.2") implementation("commons-io:commons-io:2.21.0") - testImplementation("com.squareup.okhttp3:mockwebserver3:5.3.0") + testImplementation("com.squareup.okhttp3:mockwebserver3:5.3.2") } diff --git a/jadx-plugins/jadx-aab-input/build.gradle.kts b/jadx-plugins/jadx-aab-input/build.gradle.kts index e72812b23..850992867 100644 --- a/jadx-plugins/jadx-aab-input/build.gradle.kts +++ b/jadx-plugins/jadx-aab-input/build.gradle.kts @@ -5,7 +5,7 @@ plugins { dependencies { compileOnly(project(":jadx-core")) - implementation("com.android.tools.build:aapt2-proto:8.13.2-14304508") + implementation("com.android.tools.build:aapt2-proto:9.1.0-14792394") implementation("com.google.protobuf:protobuf-java") { version { require("3.25.3") // version 4 conflict with `aapt2-proto` diff --git a/jadx-plugins/jadx-apkm-input/src/main/java/jadx/plugins/input/apkm/ApkmUtils.kt b/jadx-plugins/jadx-apkm-input/src/main/java/jadx/plugins/input/apkm/ApkmUtils.kt index 026d2ac71..d3a3f9b71 100644 --- a/jadx-plugins/jadx-apkm-input/src/main/java/jadx/plugins/input/apkm/ApkmUtils.kt +++ b/jadx-plugins/jadx-apkm-input/src/main/java/jadx/plugins/input/apkm/ApkmUtils.kt @@ -21,7 +21,5 @@ object ApkmUtils { } } - fun isSupported(manifest: ApkmManifest): Boolean { - return manifest.apkmVersion != -1 - } + fun isSupported(manifest: ApkmManifest): Boolean = manifest.apkmVersion != -1 } diff --git a/jadx-plugins/jadx-java-convert/build.gradle.kts b/jadx-plugins/jadx-java-convert/build.gradle.kts index c52a7ba66..107dd9082 100644 --- a/jadx-plugins/jadx-java-convert/build.gradle.kts +++ b/jadx-plugins/jadx-java-convert/build.gradle.kts @@ -7,7 +7,7 @@ dependencies { implementation(project(":jadx-plugins:jadx-dex-input")) implementation("com.jakewharton.android.repackaged:dalvik-dx:16.0.1") - implementation("com.android.tools:r8:8.13.17") + implementation("com.android.tools:r8:9.1.31") implementation("org.ow2.asm:asm:9.9.1") } diff --git a/jadx-plugins/jadx-java-convert/src/main/java/jadx/plugins/input/javaconvert/D8Converter.java b/jadx-plugins/jadx-java-convert/src/main/java/jadx/plugins/input/javaconvert/D8Converter.java index 24ca8a5c2..b9cca9fae 100644 --- a/jadx-plugins/jadx-java-convert/src/main/java/jadx/plugins/input/javaconvert/D8Converter.java +++ b/jadx-plugins/jadx-java-convert/src/main/java/jadx/plugins/input/javaconvert/D8Converter.java @@ -24,6 +24,9 @@ public class D8Converter { .setMinApiLevel(30) .setIntermediate(true) .setDisableDesugaring(!options.isD8Desugar()) + .setEnableVerboseSyntheticNames(true) + .setOptimizeMultidexForLinearAlloc(false) + .setIncludeClassesChecksum(false) .build(); D8.run(d8Command); } diff --git a/jadx-plugins/jadx-kotlin-metadata/build.gradle.kts b/jadx-plugins/jadx-kotlin-metadata/build.gradle.kts index c75dd57e0..0d304b4d8 100644 --- a/jadx-plugins/jadx-kotlin-metadata/build.gradle.kts +++ b/jadx-plugins/jadx-kotlin-metadata/build.gradle.kts @@ -8,7 +8,13 @@ dependencies { implementation("org.jetbrains.kotlin:kotlin-metadata-jvm:2.3.10") - testImplementation(project.project(":jadx-core").sourceSets.getByName("test").output) + testImplementation( + project + .project(":jadx-core") + .sourceSets + .getByName("test") + .output, + ) testImplementation("org.apache.commons:commons-lang3:3.20.0") testRuntimeOnly(project(":jadx-plugins:jadx-smali-input")) diff --git a/jadx-plugins/jadx-kotlin-metadata/src/main/kotlin/jadx/plugins/kotlin/metadata/KotlinMetadataOptions.kt b/jadx-plugins/jadx-kotlin-metadata/src/main/kotlin/jadx/plugins/kotlin/metadata/KotlinMetadataOptions.kt index ccaa9dbb8..ab2cb8a1e 100644 --- a/jadx-plugins/jadx-kotlin-metadata/src/main/kotlin/jadx/plugins/kotlin/metadata/KotlinMetadataOptions.kt +++ b/jadx-plugins/jadx-kotlin-metadata/src/main/kotlin/jadx/plugins/kotlin/metadata/KotlinMetadataOptions.kt @@ -56,13 +56,9 @@ class KotlinMetadataOptions : BasePluginOptionsBuilder() { .setter { isGetters = it } } - fun isPreparePassNeeded(): Boolean { - return isClassAlias - } + fun isPreparePassNeeded(): Boolean = isClassAlias - fun isDecompilePassNeeded(): Boolean { - return isMethodArgs || isFields || isCompanion || isDataClass || isToString || isGetters - } + fun isDecompilePassNeeded(): Boolean = isMethodArgs || isFields || isCompanion || isDataClass || isToString || isGetters companion object { const val CLASS_ALIAS_OPT = "$PLUGIN_ID.class-alias" diff --git a/jadx-plugins/jadx-kotlin-metadata/src/main/kotlin/jadx/plugins/kotlin/metadata/KotlinMetadataPlugin.kt b/jadx-plugins/jadx-kotlin-metadata/src/main/kotlin/jadx/plugins/kotlin/metadata/KotlinMetadataPlugin.kt index d33d6cfb8..4a59f1af3 100644 --- a/jadx-plugins/jadx-kotlin-metadata/src/main/kotlin/jadx/plugins/kotlin/metadata/KotlinMetadataPlugin.kt +++ b/jadx-plugins/jadx-kotlin-metadata/src/main/kotlin/jadx/plugins/kotlin/metadata/KotlinMetadataPlugin.kt @@ -10,9 +10,7 @@ class KotlinMetadataPlugin : JadxPlugin { private val options = KotlinMetadataOptions() - override fun getPluginInfo(): JadxPluginInfo { - return JadxPluginInfo(PLUGIN_ID, "Kotlin Metadata", "Use kotlin.Metadata annotation for code generation") - } + override fun getPluginInfo(): JadxPluginInfo = JadxPluginInfo(PLUGIN_ID, "Kotlin Metadata", "Use kotlin.Metadata annotation for code generation") override fun init(context: JadxPluginContext) { context.registerOptions(options) diff --git a/jadx-plugins/jadx-kotlin-metadata/src/main/kotlin/jadx/plugins/kotlin/metadata/pass/KotlinMetadataDecompilePass.kt b/jadx-plugins/jadx-kotlin-metadata/src/main/kotlin/jadx/plugins/kotlin/metadata/pass/KotlinMetadataDecompilePass.kt index 683503dfb..c9c520625 100644 --- a/jadx-plugins/jadx-kotlin-metadata/src/main/kotlin/jadx/plugins/kotlin/metadata/pass/KotlinMetadataDecompilePass.kt +++ b/jadx-plugins/jadx-kotlin-metadata/src/main/kotlin/jadx/plugins/kotlin/metadata/pass/KotlinMetadataDecompilePass.kt @@ -18,13 +18,11 @@ class KotlinMetadataDecompilePass( private val options: KotlinMetadataOptions, ) : JadxDecompilePass { - override fun getInfo(): JadxPassInfo { - return OrderedJadxPassInfo( - "KotlinMetadataDecompile", - "Use kotlin.Metadata annotation perform various renames", - ) - .before("CodeRenameVisitor") - } + override fun getInfo(): JadxPassInfo = OrderedJadxPassInfo( + "KotlinMetadataDecompile", + "Use kotlin.Metadata annotation perform various renames", + ) + .before("CodeRenameVisitor") override fun init(root: RootNode) { } diff --git a/jadx-plugins/jadx-kotlin-metadata/src/main/kotlin/jadx/plugins/kotlin/metadata/pass/KotlinMetadataPreparePass.kt b/jadx-plugins/jadx-kotlin-metadata/src/main/kotlin/jadx/plugins/kotlin/metadata/pass/KotlinMetadataPreparePass.kt index 285c82811..89ef637ce 100644 --- a/jadx-plugins/jadx-kotlin-metadata/src/main/kotlin/jadx/plugins/kotlin/metadata/pass/KotlinMetadataPreparePass.kt +++ b/jadx-plugins/jadx-kotlin-metadata/src/main/kotlin/jadx/plugins/kotlin/metadata/pass/KotlinMetadataPreparePass.kt @@ -12,13 +12,11 @@ class KotlinMetadataPreparePass( private val options: KotlinMetadataOptions, ) : JadxPreparePass { - override fun getInfo(): JadxPassInfo { - return OrderedJadxPassInfo( - "KotlinMetadataPrepare", - "Use kotlin.Metadata annotation to rename class & package", - ) - .before("RenameVisitor") - } + override fun getInfo(): JadxPassInfo = OrderedJadxPassInfo( + "KotlinMetadataPrepare", + "Use kotlin.Metadata annotation to rename class & package", + ) + .before("RenameVisitor") override fun init(root: RootNode) { if (options.isClassAlias) { diff --git a/jadx-plugins/jadx-kotlin-metadata/src/main/kotlin/jadx/plugins/kotlin/metadata/utils/KmClassWrapper.kt b/jadx-plugins/jadx-kotlin-metadata/src/main/kotlin/jadx/plugins/kotlin/metadata/utils/KmClassWrapper.kt index bc808bf1a..bd00f5914 100644 --- a/jadx-plugins/jadx-kotlin-metadata/src/main/kotlin/jadx/plugins/kotlin/metadata/utils/KmClassWrapper.kt +++ b/jadx-plugins/jadx-kotlin-metadata/src/main/kotlin/jadx/plugins/kotlin/metadata/utils/KmClassWrapper.kt @@ -11,25 +11,19 @@ class KmClassWrapper private constructor( private val kmCls: KmClass, ) { - fun getMethodArgs() = - KotlinMetadataUtils.mapMethodArgs(cls, kmCls) + fun getMethodArgs() = KotlinMetadataUtils.mapMethodArgs(cls, kmCls) - fun getFields() = - KotlinMetadataUtils.mapFields(cls, kmCls) + fun getFields() = KotlinMetadataUtils.mapFields(cls, kmCls) - fun getCompanion() = - KotlinMetadataUtils.mapCompanion(cls, kmCls) + fun getCompanion() = KotlinMetadataUtils.mapCompanion(cls, kmCls) - fun isDataClass() = - kmCls.isData + fun isDataClass() = kmCls.isData // does not require metadata, may be useful for plain java ? - fun parseToString() = - KotlinUtils.parseToString(cls) + fun parseToString() = KotlinUtils.parseToString(cls) // does not require metadata, may be useful for plain java ? - fun getGetters() = - KotlinUtils.findGetters(cls) + fun getGetters() = KotlinUtils.findGetters(cls) companion object { diff --git a/jadx-plugins/jadx-kotlin-metadata/src/main/kotlin/jadx/plugins/kotlin/metadata/utils/KotlinMetadataExt.kt b/jadx-plugins/jadx-kotlin-metadata/src/main/kotlin/jadx/plugins/kotlin/metadata/utils/KotlinMetadataExt.kt index 9209eb95b..318eb64db 100644 --- a/jadx-plugins/jadx-kotlin-metadata/src/main/kotlin/jadx/plugins/kotlin/metadata/utils/KotlinMetadataExt.kt +++ b/jadx-plugins/jadx-kotlin-metadata/src/main/kotlin/jadx/plugins/kotlin/metadata/utils/KotlinMetadataExt.kt @@ -48,12 +48,10 @@ private fun IAnnotation.getParamAsStringArray(paramName: String): Array? ?.toTypedArray() } -private fun IAnnotation.getParamAsIntArray(paramName: String): IntArray? { - return getParamsAsList(paramName) - ?.map(EncodedValue::getValue) - ?.map { it as Int } - ?.toIntArray() -} +private fun IAnnotation.getParamAsIntArray(paramName: String): IntArray? = getParamsAsList(paramName) + ?.map(EncodedValue::getValue) + ?.map { it as Int } + ?.toIntArray() private fun IAnnotation.getParamAsInt(paramName: String): Int? { val encodedValue = values[paramName] @@ -67,6 +65,4 @@ private fun IAnnotation.getParamAsString(paramName: String): String? { return encodedValue?.value?.let { it as String } } -fun ClassNode.getKotlinClassMetadata(): KotlinClassMetadata? { - return getMetadata()?.let(KotlinClassMetadata::readLenient) -} +fun ClassNode.getKotlinClassMetadata(): KotlinClassMetadata? = getMetadata()?.let(KotlinClassMetadata::readLenient) diff --git a/jadx-plugins/jadx-kotlin-metadata/src/main/kotlin/jadx/plugins/kotlin/metadata/utils/KotlinUtils.kt b/jadx-plugins/jadx-kotlin-metadata/src/main/kotlin/jadx/plugins/kotlin/metadata/utils/KotlinUtils.kt index 5535a701a..65bd39250 100644 --- a/jadx-plugins/jadx-kotlin-metadata/src/main/kotlin/jadx/plugins/kotlin/metadata/utils/KotlinUtils.kt +++ b/jadx-plugins/jadx-kotlin-metadata/src/main/kotlin/jadx/plugins/kotlin/metadata/utils/KotlinUtils.kt @@ -33,14 +33,12 @@ object KotlinUtils { } } - private fun getFieldGetterMethod(cls: ClassNode, field: FieldInfo): MethodNode? { - return cls.methods.firstOrNull { - it.returnType == field.type && - it.argTypes.isEmpty() && - it.insnsCount == 3 && - it.sVars.size == 2 && - (it.sVars[1].assignInsn as? IndexInsnNode)?.index == field - } + private fun getFieldGetterMethod(cls: ClassNode, field: FieldInfo): MethodNode? = cls.methods.firstOrNull { + it.returnType == field.type && + it.argTypes.isEmpty() && + it.insnsCount == 3 && + it.sVars.size == 2 && + (it.sVars[1].assignInsn as? IndexInsnNode)?.index == field } private fun getGetterAlias(fieldAlias: String): String { @@ -84,7 +82,5 @@ object KotlinUtils { } } - private fun getDefaultMethodAlias(alias: String): String { - return "$alias\$default" - } + private fun getDefaultMethodAlias(alias: String): String = "$alias\$default" } diff --git a/jadx-plugins/jadx-kotlin-metadata/src/main/kotlin/jadx/plugins/kotlin/metadata/utils/LogExt.kt b/jadx-plugins/jadx-kotlin-metadata/src/main/kotlin/jadx/plugins/kotlin/metadata/utils/LogExt.kt index 62e1152dd..e15043761 100644 --- a/jadx-plugins/jadx-kotlin-metadata/src/main/kotlin/jadx/plugins/kotlin/metadata/utils/LogExt.kt +++ b/jadx-plugins/jadx-kotlin-metadata/src/main/kotlin/jadx/plugins/kotlin/metadata/utils/LogExt.kt @@ -5,6 +5,5 @@ import org.slf4j.LoggerFactory inline val T.LOG: Logger get() = LoggerFactory.getLogger(T::class.java) -inline fun T.runCatchingLog(msg: String? = null, block: () -> R) = - runCatching(block) - .onFailure { LOG.error(msg.orEmpty(), it) } +inline fun T.runCatchingLog(msg: String? = null, block: () -> R) = runCatching(block) + .onFailure { LOG.error(msg.orEmpty(), it) } diff --git a/jadx-plugins/jadx-kotlin-metadata/src/main/kotlin/jadx/plugins/kotlin/metadata/utils/ToStringParser.kt b/jadx-plugins/jadx-kotlin-metadata/src/main/kotlin/jadx/plugins/kotlin/metadata/utils/ToStringParser.kt index baa696108..821620ced 100644 --- a/jadx-plugins/jadx-kotlin-metadata/src/main/kotlin/jadx/plugins/kotlin/metadata/utils/ToStringParser.kt +++ b/jadx-plugins/jadx-kotlin-metadata/src/main/kotlin/jadx/plugins/kotlin/metadata/utils/ToStringParser.kt @@ -124,23 +124,17 @@ class ToStringParser private constructor(mthToString: MethodNode) { ) } - private fun isStartStringBuilder(inst: InsnNode): Boolean { - return inst is ConstructorInsn && - inst.isNewInstance && - inst.callMth.declClass.fullName == Consts.CLASS_STRING_BUILDER - } + private fun isStartStringBuilder(inst: InsnNode): Boolean = inst is ConstructorInsn && + inst.isNewInstance && + inst.callMth.declClass.fullName == Consts.CLASS_STRING_BUILDER - private fun isAppendInvoke(inst: InsnNode): Boolean { - return inst is InvokeNode && - inst.callMth.declClass.fullName == Consts.CLASS_STRING_BUILDER && - inst.callMth.name == "append" && - inst.argsCount == 2 - } + private fun isAppendInvoke(inst: InsnNode): Boolean = inst is InvokeNode && + inst.callMth.declClass.fullName == Consts.CLASS_STRING_BUILDER && + inst.callMth.name == "append" && + inst.argsCount == 2 - private fun isToString(inst: InsnNode): Boolean { - return inst is InvokeNode && - inst.callMth.declClass.fullName == Consts.CLASS_STRING_BUILDER && - inst.callMth.shortId == Consts.MTH_TOSTRING_SIGNATURE - } + private fun isToString(inst: InsnNode): Boolean = inst is InvokeNode && + inst.callMth.declClass.fullName == Consts.CLASS_STRING_BUILDER && + inst.callMth.shortId == Consts.MTH_TOSTRING_SIGNATURE } } diff --git a/jadx-plugins/jadx-kotlin-metadata/src/test/kotlin/TestKotlinMetadata.kt b/jadx-plugins/jadx-kotlin-metadata/src/test/kotlin/TestKotlinMetadata.kt index 1d6a6e00f..d1cd76941 100644 --- a/jadx-plugins/jadx-kotlin-metadata/src/test/kotlin/TestKotlinMetadata.kt +++ b/jadx-plugins/jadx-kotlin-metadata/src/test/kotlin/TestKotlinMetadata.kt @@ -159,7 +159,6 @@ class TestKotlinMetadata : SmaliTest() { } } - private fun assertThatClass(): JadxCodeAssertions = - assertThat(getClassNodeFromSmaliFiles("deobf", "TestKotlinMetadata", "a")) - .code() + private fun assertThatClass(): JadxCodeAssertions = assertThat(getClassNodeFromSmaliFiles("deobf", "TestKotlinMetadata", "a")) + .code() } diff --git a/jadx-plugins/jadx-kotlin-source-debug-extension/build.gradle.kts b/jadx-plugins/jadx-kotlin-source-debug-extension/build.gradle.kts index 2b0de7516..b97370a02 100644 --- a/jadx-plugins/jadx-kotlin-source-debug-extension/build.gradle.kts +++ b/jadx-plugins/jadx-kotlin-source-debug-extension/build.gradle.kts @@ -6,7 +6,13 @@ plugins { dependencies { api(project(":jadx-core")) - testImplementation(project.project(":jadx-core").sourceSets.getByName("test").output) + testImplementation( + project + .project(":jadx-core") + .sourceSets + .getByName("test") + .output, + ) testImplementation("org.apache.commons:commons-lang3:3.20.0") testRuntimeOnly(project(":jadx-plugins:jadx-smali-input")) diff --git a/jadx-plugins/jadx-kotlin-source-debug-extension/src/main/kotlin/jadx/plugins/kotlin/smap/KotlinSmapOptions.kt b/jadx-plugins/jadx-kotlin-source-debug-extension/src/main/kotlin/jadx/plugins/kotlin/smap/KotlinSmapOptions.kt index 66fb8d846..d0ade339b 100644 --- a/jadx-plugins/jadx-kotlin-source-debug-extension/src/main/kotlin/jadx/plugins/kotlin/smap/KotlinSmapOptions.kt +++ b/jadx-plugins/jadx-kotlin-source-debug-extension/src/main/kotlin/jadx/plugins/kotlin/smap/KotlinSmapOptions.kt @@ -14,9 +14,7 @@ class KotlinSmapOptions : BasePluginOptionsBuilder() { .setter { isClassAliasSourceDbg = it } } - fun isClassSourceDbg(): Boolean { - return isClassAliasSourceDbg - } + fun isClassSourceDbg(): Boolean = isClassAliasSourceDbg companion object { const val CLASS_ALIAS_SOURCE_DBG_OPT = "$PLUGIN_ID.class-alias-source-dbg" diff --git a/jadx-plugins/jadx-kotlin-source-debug-extension/src/main/kotlin/jadx/plugins/kotlin/smap/KotlinSmapPlugin.kt b/jadx-plugins/jadx-kotlin-source-debug-extension/src/main/kotlin/jadx/plugins/kotlin/smap/KotlinSmapPlugin.kt index dc0db850d..57c2f0bb3 100644 --- a/jadx-plugins/jadx-kotlin-source-debug-extension/src/main/kotlin/jadx/plugins/kotlin/smap/KotlinSmapPlugin.kt +++ b/jadx-plugins/jadx-kotlin-source-debug-extension/src/main/kotlin/jadx/plugins/kotlin/smap/KotlinSmapPlugin.kt @@ -9,9 +9,7 @@ class KotlinSmapPlugin : JadxPlugin { private val options = KotlinSmapOptions() - override fun getPluginInfo(): JadxPluginInfo { - return JadxPluginInfo(PLUGIN_ID, "Kotlin SMAP", "Use kotlin.SourceDebugExtension annotation for rename class alias") - } + override fun getPluginInfo(): JadxPluginInfo = JadxPluginInfo(PLUGIN_ID, "Kotlin SMAP", "Use kotlin.SourceDebugExtension annotation for rename class alias") override fun init(context: JadxPluginContext) { context.registerOptions(options) diff --git a/jadx-plugins/jadx-kotlin-source-debug-extension/src/main/kotlin/jadx/plugins/kotlin/smap/model/SMAP.kt b/jadx-plugins/jadx-kotlin-source-debug-extension/src/main/kotlin/jadx/plugins/kotlin/smap/model/SMAP.kt index 8f0296292..db0065c69 100644 --- a/jadx-plugins/jadx-kotlin-source-debug-extension/src/main/kotlin/jadx/plugins/kotlin/smap/model/SMAP.kt +++ b/jadx-plugins/jadx-kotlin-source-debug-extension/src/main/kotlin/jadx/plugins/kotlin/smap/model/SMAP.kt @@ -33,12 +33,11 @@ class SMAP(val fileMappings: List) { class FileMapping(val name: String, val path: String) { val lineMappings = arrayListOf() - fun toSourceInfo(): SourceInfo = - SourceInfo( - name, - path, - lineMappings.fold(0) { result, mapping -> max(result, mapping.source + mapping.range - 1) }, - ) + fun toSourceInfo(): SourceInfo = SourceInfo( + name, + path, + lineMappings.fold(0) { result, mapping -> max(result, mapping.source + mapping.range - 1) }, + ) fun mapNewLineNumber(source: Int, currentIndex: Int, callSite: SourcePosition?): Int { // Save some space in the SMAP by reusing (or extending if it's the last one) the existing range. @@ -51,25 +50,19 @@ class FileMapping(val name: String, val path: String) { return mapping.mapSourceToDest(source) } - private fun RangeMapping.canReuseFor(newSource: Int, globalMaxDest: Int, newCallSite: SourcePosition?): Boolean = - callSite == newCallSite && (newSource - source) in 0 until range + (if (globalMaxDest in this) 10 else 0) + private fun RangeMapping.canReuseFor(newSource: Int, globalMaxDest: Int, newCallSite: SourcePosition?): Boolean = callSite == newCallSite && (newSource - source) in 0 until range + (if (globalMaxDest in this) 10 else 0) - fun mapNewInterval(source: Int, dest: Int, range: Int, callSite: SourcePosition? = null): RangeMapping = - RangeMapping(source, dest, range, callSite, parent = this).also { lineMappings.add(it) } + fun mapNewInterval(source: Int, dest: Int, range: Int, callSite: SourcePosition? = null): RangeMapping = RangeMapping(source, dest, range, callSite, parent = this).also { lineMappings.add(it) } } data class RangeMapping(val source: Int, val dest: Int, var range: Int, val callSite: SourcePosition?, val parent: FileMapping) { - operator fun contains(destLine: Int): Boolean = - dest <= destLine && destLine < dest + range + operator fun contains(destLine: Int): Boolean = dest <= destLine && destLine < dest + range - fun hasMappingForSource(sourceLine: Int): Boolean = - source <= sourceLine && sourceLine < source + range + fun hasMappingForSource(sourceLine: Int): Boolean = source <= sourceLine && sourceLine < source + range - fun mapDestToSource(destLine: Int): SourcePosition = - SourcePosition(source + (destLine - dest), parent.name, parent.path) + fun mapDestToSource(destLine: Int): SourcePosition = SourcePosition(source + (destLine - dest), parent.name, parent.path) - fun mapSourceToDest(sourceLine: Int): Int = - dest + (sourceLine - source) + fun mapSourceToDest(sourceLine: Int): Int = dest + (sourceLine - source) } val RangeMapping.toRange: IntRange diff --git a/jadx-plugins/jadx-kotlin-source-debug-extension/src/main/kotlin/jadx/plugins/kotlin/smap/pass/KotlinSourceDebugExtensionPass.kt b/jadx-plugins/jadx-kotlin-source-debug-extension/src/main/kotlin/jadx/plugins/kotlin/smap/pass/KotlinSourceDebugExtensionPass.kt index 95a9e75f6..561f362d4 100644 --- a/jadx-plugins/jadx-kotlin-source-debug-extension/src/main/kotlin/jadx/plugins/kotlin/smap/pass/KotlinSourceDebugExtensionPass.kt +++ b/jadx-plugins/jadx-kotlin-source-debug-extension/src/main/kotlin/jadx/plugins/kotlin/smap/pass/KotlinSourceDebugExtensionPass.kt @@ -12,13 +12,11 @@ class KotlinSourceDebugExtensionPass( private val options: KotlinSmapOptions, ) : JadxPreparePass { - override fun getInfo(): JadxPassInfo { - return OrderedJadxPassInfo( - "SourceDebugExtensionPrepare", - "Use kotlin.jvm.internal.SourceDebugExtension annotation to rename class & package", - ) - .before("RenameVisitor") - } + override fun getInfo(): JadxPassInfo = OrderedJadxPassInfo( + "SourceDebugExtensionPrepare", + "Use kotlin.jvm.internal.SourceDebugExtension annotation to rename class & package", + ) + .before("RenameVisitor") override fun init(root: RootNode) { if (options.isClassAliasSourceDbg) { diff --git a/jadx-plugins/jadx-kotlin-source-debug-extension/src/main/kotlin/jadx/plugins/kotlin/smap/utils/SMAPParser.kt b/jadx-plugins/jadx-kotlin-source-debug-extension/src/main/kotlin/jadx/plugins/kotlin/smap/utils/SMAPParser.kt index 25209dd89..0f43b7a6b 100644 --- a/jadx-plugins/jadx-kotlin-source-debug-extension/src/main/kotlin/jadx/plugins/kotlin/smap/utils/SMAPParser.kt +++ b/jadx-plugins/jadx-kotlin-source-debug-extension/src/main/kotlin/jadx/plugins/kotlin/smap/utils/SMAPParser.kt @@ -22,12 +22,11 @@ import jadx.plugins.kotlin.smap.model.KOTLIN_STRATA_NAME import jadx.plugins.kotlin.smap.model.SMAP object SMAPParser { - fun parseOrNull(mappingInfo: String): SMAP? = - if (mappingInfo.isNotEmpty()) { - parseStratum(mappingInfo, KOTLIN_STRATA_NAME, parseStratum(mappingInfo, KOTLIN_DEBUG_STRATA_NAME, null)) - } else { - null - } + fun parseOrNull(mappingInfo: String): SMAP? = if (mappingInfo.isNotEmpty()) { + parseStratum(mappingInfo, KOTLIN_STRATA_NAME, parseStratum(mappingInfo, KOTLIN_DEBUG_STRATA_NAME, null)) + } else { + null + } private class SMAPTokenizer(private val text: String, private val headerString: String) : Iterator { @@ -55,9 +54,7 @@ object SMAPParser { pos++ } - override fun hasNext(): Boolean { - return currentLine != null - } + override fun hasNext(): Boolean = currentLine != null override fun next(): String { val res = currentLine ?: throw NoSuchElementException() @@ -105,7 +102,9 @@ object SMAPParser { val range = when { // These two fields have a different meaning, but for compatibility we treat them the same. See `SMAPBuilder`. destMultiplierSeparator != line.length -> line.substring(destMultiplierSeparator + 1).toInt() + sourceRangeSeparator != destSeparator -> line.substring(sourceRangeSeparator + 1, destSeparator).toInt() + else -> 1 } // Here we assume that each range in `Kotlin` is entirely within at most one range in `KotlinDebug`. diff --git a/jadx-plugins/jadx-kotlin-source-debug-extension/src/test/kotlin/TestSourceDebugExtension.kt b/jadx-plugins/jadx-kotlin-source-debug-extension/src/test/kotlin/TestSourceDebugExtension.kt index 3aa34d8c5..eb24b8271 100644 --- a/jadx-plugins/jadx-kotlin-source-debug-extension/src/test/kotlin/TestSourceDebugExtension.kt +++ b/jadx-plugins/jadx-kotlin-source-debug-extension/src/test/kotlin/TestSourceDebugExtension.kt @@ -28,7 +28,6 @@ class TestSourceDebugExtension : SmaliTest() { } } - private fun assertThatClass(): JadxCodeAssertions = - assertThat(getClassNodeFromSmaliFiles("deobf", "TestKotlinSourceDebugExtension", "C6")) - .code() + private fun assertThatClass(): JadxCodeAssertions = assertThat(getClassNodeFromSmaliFiles("deobf", "TestKotlinSourceDebugExtension", "C6")) + .code() }