chore: update gradle and dependencies
This commit is contained in:
@@ -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)
|
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
|
### 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
|
git clone https://github.com/skylot/jadx.git
|
||||||
cd jadx
|
cd jadx
|
||||||
|
|||||||
+4
-2
@@ -8,7 +8,7 @@ import java.util.Locale
|
|||||||
plugins {
|
plugins {
|
||||||
id("com.github.ben-manes.versions") version "0.53.0"
|
id("com.github.ben-manes.versions") version "0.53.0"
|
||||||
id("se.patrikerdes.use-latest-versions") version "0.2.19"
|
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" }
|
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")) {
|
from(tasks.getByPath(":jadx-cli:installShadowDist")) {
|
||||||
exclude("**/*.jar")
|
exclude("**/*.jar")
|
||||||
filter { line ->
|
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")
|
||||||
.replace("-jar \"%CLASSPATH%\"", "-cp \"%CLASSPATH%\" jadx.cli.JadxCLI")
|
.replace("-jar \"%CLASSPATH%\"", "-cp \"%CLASSPATH%\" jadx.cli.JadxCLI")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,15 +15,15 @@ version = jadxVersion
|
|||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation("org.slf4j:slf4j-api:2.0.17")
|
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("ch.qos.logback:logback-classic:1.5.32")
|
||||||
testImplementation("org.assertj:assertj-core:3.27.6")
|
testImplementation("org.assertj:assertj-core:3.27.7")
|
||||||
|
|
||||||
testImplementation("org.junit.jupiter:junit-jupiter:5.13.3")
|
testImplementation("org.junit.jupiter:junit-jupiter:5.13.3")
|
||||||
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
|
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
|
||||||
|
|
||||||
testCompileOnly("org.jetbrains:annotations:26.0.2")
|
testCompileOnly("org.jetbrains:annotations:26.1.0")
|
||||||
}
|
}
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
|
|||||||
@@ -7,10 +7,10 @@ repositories {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
rewrite("org.openrewrite.recipe:rewrite-testing-frameworks:3.24.0")
|
rewrite("org.openrewrite.recipe:rewrite-testing-frameworks:3.30.0")
|
||||||
rewrite("org.openrewrite.recipe:rewrite-logging-frameworks:3.20.0")
|
rewrite("org.openrewrite.recipe:rewrite-logging-frameworks:3.26.0")
|
||||||
rewrite("org.openrewrite.recipe:rewrite-migrate-java:3.24.0")
|
rewrite("org.openrewrite.recipe:rewrite-migrate-java:3.30.1")
|
||||||
rewrite("org.openrewrite.recipe:rewrite-static-analysis:2.24.0")
|
rewrite("org.openrewrite.recipe:rewrite-static-analysis:2.30.1")
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks {
|
tasks {
|
||||||
|
|||||||
Vendored
BIN
Binary file not shown.
+2
-2
@@ -1,7 +1,7 @@
|
|||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
distributionSha256Sum=72f44c9f8ebcb1af43838f45ee5c4aa9c5444898b3468ab3f4af7b6076c5bc3f
|
distributionSha256Sum=2ab2958f2a1e51120c326cad6f385153bb11ee93b3c216c5fccebfdfbb7ec6cb
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-9.2.1-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-9.4.1-bin.zip
|
||||||
networkTimeout=10000
|
networkTimeout=10000
|
||||||
validateDistributionUrl=true
|
validateDistributionUrl=true
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
|
|||||||
@@ -57,7 +57,7 @@
|
|||||||
# Darwin, MinGW, and NonStop.
|
# Darwin, MinGW, and NonStop.
|
||||||
#
|
#
|
||||||
# (3) This script is generated from the Groovy template
|
# (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.
|
# within the Gradle project.
|
||||||
#
|
#
|
||||||
# You can find Gradle at https://github.com/gradle/gradle/.
|
# You can find Gradle at https://github.com/gradle/gradle/.
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ dependencies {
|
|||||||
runtimeOnly(project(":jadx-plugins:jadx-apks-input"))
|
runtimeOnly(project(":jadx-plugins:jadx-apks-input"))
|
||||||
|
|
||||||
implementation("org.jcommander:jcommander:2.0")
|
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")
|
implementation("com.google.code.gson:gson:2.13.2")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ dependencies {
|
|||||||
strictly("[3.33, 3.34[") // from 3.34 compiled with Java 17
|
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()
|
val jadxTestJavaVersion = getTestJavaVersion()
|
||||||
@@ -32,7 +32,10 @@ val jadxTestJavaVersion = getTestJavaVersion()
|
|||||||
fun getTestJavaVersion(): Int? {
|
fun getTestJavaVersion(): Int? {
|
||||||
val envVarName = "JADX_TEST_JAVA_VERSION"
|
val envVarName = "JADX_TEST_JAVA_VERSION"
|
||||||
val testJavaVer = System.getenv(envVarName)?.toInt() ?: return null
|
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) {
|
if (testJavaVer < currentJavaVer) {
|
||||||
throw GradleException("'$envVarName' can't be set to lower version than $currentJavaVer")
|
throw GradleException("'$envVarName' can't be set to lower version than $currentJavaVer")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -55,7 +55,13 @@ dependencies {
|
|||||||
implementation("com.eclipsesource.j2v8:j2v8_linux_x86_64:4.6.0")
|
implementation("com.eclipsesource.j2v8:j2v8_linux_x86_64:4.6.0")
|
||||||
implementation("com.eclipsesource.j2v8:j2v8_win32_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
|
val jadxVersion: String by rootProject.extra
|
||||||
@@ -119,12 +125,14 @@ project.components.withType(AdhocComponentWithVariants::class.java).forEach { c
|
|||||||
tasks.startShadowScripts {
|
tasks.startShadowScripts {
|
||||||
doLast {
|
doLast {
|
||||||
val newWindowsScriptContent =
|
val newWindowsScriptContent =
|
||||||
windowsScript.readText()
|
windowsScript
|
||||||
|
.readText()
|
||||||
.replace("java.exe", "javaw.exe")
|
.replace("java.exe", "javaw.exe")
|
||||||
.replace("\"%JAVA_EXE%\" %DEFAULT_JVM_OPTS%", "start \"jadx-gui\" /B \"%JAVA_EXE%\" %DEFAULT_JVM_OPTS%")
|
.replace("\"%JAVA_EXE%\" %DEFAULT_JVM_OPTS%", "start \"jadx-gui\" /B \"%JAVA_EXE%\" %DEFAULT_JVM_OPTS%")
|
||||||
// Add launch script path as a property
|
// Add launch script path as a property
|
||||||
val newUnixScriptContent =
|
val newUnixScriptContent =
|
||||||
unixScript.readText()
|
unixScript
|
||||||
|
.readText()
|
||||||
.replace(
|
.replace(
|
||||||
Regex("DEFAULT_JVM_OPTS=.+", RegexOption.MULTILINE),
|
Regex("DEFAULT_JVM_OPTS=.+", RegexOption.MULTILINE),
|
||||||
{ result -> result.value + "\" \\\"-Djadx.launchScript.path=\$(realpath $0)\\\"\"" },
|
{ result -> result.value + "\" \\\"-Djadx.launchScript.path=\$(realpath $0)\\\"\"" },
|
||||||
@@ -151,18 +159,24 @@ launch4j {
|
|||||||
supportUrl.set("https://github.com/skylot/jadx")
|
supportUrl.set("https://github.com/skylot/jadx")
|
||||||
|
|
||||||
bundledJrePath.set(if (project.hasProperty("bundleJRE")) "%EXEDIR%/jre" else "%JAVA_HOME%")
|
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()}")
|
println("Launch4J classpath: ${classpath.get()}")
|
||||||
|
|
||||||
chdir.set("") // don't change current dir
|
chdir.set("") // don't change current dir
|
||||||
libraryDir.set("") // don't add any libs
|
libraryDir.set("") // don't add any libs
|
||||||
}
|
}
|
||||||
|
|
||||||
fun escapeJVMOptions(): List<String> {
|
fun escapeJVMOptions(): List<String> =
|
||||||
return application.applicationDefaultJvmArgs
|
application.applicationDefaultJvmArgs
|
||||||
.toList()
|
.toList()
|
||||||
.map { if (it.startsWith("-D")) "\"$it\"" else it }
|
.map { if (it.startsWith("-D")) "\"$it\"" else it }
|
||||||
}
|
|
||||||
|
|
||||||
runtime {
|
runtime {
|
||||||
addOptions("--strip-debug", "--no-header-files", "--no-man-pages")
|
addOptions("--strip-debug", "--no-header-files", "--no-man-pages")
|
||||||
|
|||||||
@@ -32,18 +32,14 @@ class XposedAction(codeArea: CodeArea) : JNodeAction(ActionModel.XPOSED_COPY, co
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun isActionEnabled(node: JNode?): Boolean {
|
override fun isActionEnabled(node: JNode?): Boolean = node is JMethod || node is JClass || node is JField
|
||||||
return node is JMethod || node is JClass || node is JField
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun generateXposedSnippet(node: JNode): String {
|
private fun generateXposedSnippet(node: JNode): String = when (node) {
|
||||||
return when (node) {
|
|
||||||
is JMethod -> generateMethodSnippet(node)
|
is JMethod -> generateMethodSnippet(node)
|
||||||
is JClass -> generateClassSnippet(node)
|
is JClass -> generateClassSnippet(node)
|
||||||
is JField -> generateFieldSnippet(node)
|
is JField -> generateFieldSnippet(node)
|
||||||
else -> throw JadxRuntimeException("Unsupported node type: " + node.javaClass)
|
else -> throw JadxRuntimeException("Unsupported node type: " + node.javaClass)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private fun generateMethodSnippet(jMethod: JMethod): String {
|
private fun generateMethodSnippet(jMethod: JMethod): String {
|
||||||
val javaMethod = jMethod.javaMethod
|
val javaMethod = jMethod.javaMethod
|
||||||
@@ -73,6 +69,7 @@ class XposedAction(codeArea: CodeArea) : JNodeAction(ActionModel.XPOSED_COPY, co
|
|||||||
super.afterHookedMethod(param);
|
super.afterHookedMethod(param);
|
||||||
}
|
}
|
||||||
});"""
|
});"""
|
||||||
|
|
||||||
XposedCodegenLanguage.KOTLIN ->
|
XposedCodegenLanguage.KOTLIN ->
|
||||||
"""XposedHelpers.%s("%s", classLoader, %s, object : XC_MethodHook() {
|
"""XposedHelpers.%s("%s", classLoader, %s, object : XC_MethodHook() {
|
||||||
override fun beforeHookedMethod(param: MethodHookParam) {
|
override fun beforeHookedMethod(param: MethodHookParam) {
|
||||||
@@ -88,12 +85,14 @@ class XposedAction(codeArea: CodeArea) : JNodeAction(ActionModel.XPOSED_COPY, co
|
|||||||
return String.format(template, xposedMethod, rawClassName, args.joinToString(", "))
|
return String.format(template, xposedMethod, rawClassName, args.joinToString(", "))
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun fixTypeContent(type: ArgType): String {
|
private fun fixTypeContent(type: ArgType): String = when {
|
||||||
return when {
|
|
||||||
type.isGeneric -> "\"${type.`object`}\""
|
type.isGeneric -> "\"${type.`object`}\""
|
||||||
|
|
||||||
type.isGenericType && type.isObject && type.isTypeKnown -> "java.lang.Object"
|
type.isGenericType && type.isObject && type.isTypeKnown -> "java.lang.Object"
|
||||||
|
|
||||||
type.isPrimitive -> when (language) {
|
type.isPrimitive -> when (language) {
|
||||||
XposedCodegenLanguage.JAVA -> "$type.class"
|
XposedCodegenLanguage.JAVA -> "$type.class"
|
||||||
|
|
||||||
XposedCodegenLanguage.KOTLIN -> when (type.primitiveType) {
|
XposedCodegenLanguage.KOTLIN -> when (type.primitiveType) {
|
||||||
PrimitiveType.BOOLEAN -> "Boolean::class.javaPrimitiveType"
|
PrimitiveType.BOOLEAN -> "Boolean::class.javaPrimitiveType"
|
||||||
PrimitiveType.CHAR -> "Char::class.javaPrimitiveType"
|
PrimitiveType.CHAR -> "Char::class.javaPrimitiveType"
|
||||||
@@ -109,9 +108,9 @@ class XposedAction(codeArea: CodeArea) : JNodeAction(ActionModel.XPOSED_COPY, co
|
|||||||
else -> throw JadxRuntimeException("Unknown or null primitive type: $type")
|
else -> throw JadxRuntimeException("Unknown or null primitive type: $type")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> "\"$type\""
|
else -> "\"$type\""
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private fun generateClassSnippet(jClass: JClass): String {
|
private fun generateClassSnippet(jClass: JClass): String {
|
||||||
val javaClass = jClass.cls
|
val javaClass = jClass.cls
|
||||||
|
|||||||
@@ -11,5 +11,5 @@ dependencies {
|
|||||||
implementation("com.google.code.gson:gson:2.13.2")
|
implementation("com.google.code.gson:gson:2.13.2")
|
||||||
implementation("commons-io:commons-io:2.21.0")
|
implementation("commons-io:commons-io:2.21.0")
|
||||||
|
|
||||||
testImplementation("com.squareup.okhttp3:mockwebserver3:5.3.0")
|
testImplementation("com.squareup.okhttp3:mockwebserver3:5.3.2")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ plugins {
|
|||||||
dependencies {
|
dependencies {
|
||||||
compileOnly(project(":jadx-core"))
|
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") {
|
implementation("com.google.protobuf:protobuf-java") {
|
||||||
version {
|
version {
|
||||||
require("3.25.3") // version 4 conflict with `aapt2-proto`
|
require("3.25.3") // version 4 conflict with `aapt2-proto`
|
||||||
|
|||||||
@@ -21,7 +21,5 @@ object ApkmUtils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun isSupported(manifest: ApkmManifest): Boolean {
|
fun isSupported(manifest: ApkmManifest): Boolean = manifest.apkmVersion != -1
|
||||||
return manifest.apkmVersion != -1
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ dependencies {
|
|||||||
|
|
||||||
implementation(project(":jadx-plugins:jadx-dex-input"))
|
implementation(project(":jadx-plugins:jadx-dex-input"))
|
||||||
implementation("com.jakewharton.android.repackaged:dalvik-dx:16.0.1")
|
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")
|
implementation("org.ow2.asm:asm:9.9.1")
|
||||||
}
|
}
|
||||||
|
|||||||
+3
@@ -24,6 +24,9 @@ public class D8Converter {
|
|||||||
.setMinApiLevel(30)
|
.setMinApiLevel(30)
|
||||||
.setIntermediate(true)
|
.setIntermediate(true)
|
||||||
.setDisableDesugaring(!options.isD8Desugar())
|
.setDisableDesugaring(!options.isD8Desugar())
|
||||||
|
.setEnableVerboseSyntheticNames(true)
|
||||||
|
.setOptimizeMultidexForLinearAlloc(false)
|
||||||
|
.setIncludeClassesChecksum(false)
|
||||||
.build();
|
.build();
|
||||||
D8.run(d8Command);
|
D8.run(d8Command);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,13 @@ dependencies {
|
|||||||
|
|
||||||
implementation("org.jetbrains.kotlin:kotlin-metadata-jvm:2.3.10")
|
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")
|
testImplementation("org.apache.commons:commons-lang3:3.20.0")
|
||||||
|
|
||||||
testRuntimeOnly(project(":jadx-plugins:jadx-smali-input"))
|
testRuntimeOnly(project(":jadx-plugins:jadx-smali-input"))
|
||||||
|
|||||||
+2
-6
@@ -56,13 +56,9 @@ class KotlinMetadataOptions : BasePluginOptionsBuilder() {
|
|||||||
.setter { isGetters = it }
|
.setter { isGetters = it }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun isPreparePassNeeded(): Boolean {
|
fun isPreparePassNeeded(): Boolean = isClassAlias
|
||||||
return isClassAlias
|
|
||||||
}
|
|
||||||
|
|
||||||
fun isDecompilePassNeeded(): Boolean {
|
fun isDecompilePassNeeded(): Boolean = isMethodArgs || isFields || isCompanion || isDataClass || isToString || isGetters
|
||||||
return isMethodArgs || isFields || isCompanion || isDataClass || isToString || isGetters
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val CLASS_ALIAS_OPT = "$PLUGIN_ID.class-alias"
|
const val CLASS_ALIAS_OPT = "$PLUGIN_ID.class-alias"
|
||||||
|
|||||||
+1
-3
@@ -10,9 +10,7 @@ class KotlinMetadataPlugin : JadxPlugin {
|
|||||||
|
|
||||||
private val options = KotlinMetadataOptions()
|
private val options = KotlinMetadataOptions()
|
||||||
|
|
||||||
override fun getPluginInfo(): JadxPluginInfo {
|
override fun getPluginInfo(): JadxPluginInfo = JadxPluginInfo(PLUGIN_ID, "Kotlin Metadata", "Use kotlin.Metadata annotation for code generation")
|
||||||
return JadxPluginInfo(PLUGIN_ID, "Kotlin Metadata", "Use kotlin.Metadata annotation for code generation")
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun init(context: JadxPluginContext) {
|
override fun init(context: JadxPluginContext) {
|
||||||
context.registerOptions(options)
|
context.registerOptions(options)
|
||||||
|
|||||||
+1
-3
@@ -18,13 +18,11 @@ class KotlinMetadataDecompilePass(
|
|||||||
private val options: KotlinMetadataOptions,
|
private val options: KotlinMetadataOptions,
|
||||||
) : JadxDecompilePass {
|
) : JadxDecompilePass {
|
||||||
|
|
||||||
override fun getInfo(): JadxPassInfo {
|
override fun getInfo(): JadxPassInfo = OrderedJadxPassInfo(
|
||||||
return OrderedJadxPassInfo(
|
|
||||||
"KotlinMetadataDecompile",
|
"KotlinMetadataDecompile",
|
||||||
"Use kotlin.Metadata annotation perform various renames",
|
"Use kotlin.Metadata annotation perform various renames",
|
||||||
)
|
)
|
||||||
.before("CodeRenameVisitor")
|
.before("CodeRenameVisitor")
|
||||||
}
|
|
||||||
|
|
||||||
override fun init(root: RootNode) {
|
override fun init(root: RootNode) {
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-3
@@ -12,13 +12,11 @@ class KotlinMetadataPreparePass(
|
|||||||
private val options: KotlinMetadataOptions,
|
private val options: KotlinMetadataOptions,
|
||||||
) : JadxPreparePass {
|
) : JadxPreparePass {
|
||||||
|
|
||||||
override fun getInfo(): JadxPassInfo {
|
override fun getInfo(): JadxPassInfo = OrderedJadxPassInfo(
|
||||||
return OrderedJadxPassInfo(
|
|
||||||
"KotlinMetadataPrepare",
|
"KotlinMetadataPrepare",
|
||||||
"Use kotlin.Metadata annotation to rename class & package",
|
"Use kotlin.Metadata annotation to rename class & package",
|
||||||
)
|
)
|
||||||
.before("RenameVisitor")
|
.before("RenameVisitor")
|
||||||
}
|
|
||||||
|
|
||||||
override fun init(root: RootNode) {
|
override fun init(root: RootNode) {
|
||||||
if (options.isClassAlias) {
|
if (options.isClassAlias) {
|
||||||
|
|||||||
+6
-12
@@ -11,25 +11,19 @@ class KmClassWrapper private constructor(
|
|||||||
private val kmCls: KmClass,
|
private val kmCls: KmClass,
|
||||||
) {
|
) {
|
||||||
|
|
||||||
fun getMethodArgs() =
|
fun getMethodArgs() = KotlinMetadataUtils.mapMethodArgs(cls, kmCls)
|
||||||
KotlinMetadataUtils.mapMethodArgs(cls, kmCls)
|
|
||||||
|
|
||||||
fun getFields() =
|
fun getFields() = KotlinMetadataUtils.mapFields(cls, kmCls)
|
||||||
KotlinMetadataUtils.mapFields(cls, kmCls)
|
|
||||||
|
|
||||||
fun getCompanion() =
|
fun getCompanion() = KotlinMetadataUtils.mapCompanion(cls, kmCls)
|
||||||
KotlinMetadataUtils.mapCompanion(cls, kmCls)
|
|
||||||
|
|
||||||
fun isDataClass() =
|
fun isDataClass() = kmCls.isData
|
||||||
kmCls.isData
|
|
||||||
|
|
||||||
// does not require metadata, may be useful for plain java ?
|
// does not require metadata, may be useful for plain java ?
|
||||||
fun parseToString() =
|
fun parseToString() = KotlinUtils.parseToString(cls)
|
||||||
KotlinUtils.parseToString(cls)
|
|
||||||
|
|
||||||
// does not require metadata, may be useful for plain java ?
|
// does not require metadata, may be useful for plain java ?
|
||||||
fun getGetters() =
|
fun getGetters() = KotlinUtils.findGetters(cls)
|
||||||
KotlinUtils.findGetters(cls)
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
|
|||||||
+2
-6
@@ -48,12 +48,10 @@ private fun IAnnotation.getParamAsStringArray(paramName: String): Array<String>?
|
|||||||
?.toTypedArray()
|
?.toTypedArray()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun IAnnotation.getParamAsIntArray(paramName: String): IntArray? {
|
private fun IAnnotation.getParamAsIntArray(paramName: String): IntArray? = getParamsAsList(paramName)
|
||||||
return getParamsAsList(paramName)
|
|
||||||
?.map<EncodedValue, Any?>(EncodedValue::getValue)
|
?.map<EncodedValue, Any?>(EncodedValue::getValue)
|
||||||
?.map { it as Int }
|
?.map { it as Int }
|
||||||
?.toIntArray()
|
?.toIntArray()
|
||||||
}
|
|
||||||
|
|
||||||
private fun IAnnotation.getParamAsInt(paramName: String): Int? {
|
private fun IAnnotation.getParamAsInt(paramName: String): Int? {
|
||||||
val encodedValue = values[paramName]
|
val encodedValue = values[paramName]
|
||||||
@@ -67,6 +65,4 @@ private fun IAnnotation.getParamAsString(paramName: String): String? {
|
|||||||
return encodedValue?.value?.let { it as String }
|
return encodedValue?.value?.let { it as String }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun ClassNode.getKotlinClassMetadata(): KotlinClassMetadata? {
|
fun ClassNode.getKotlinClassMetadata(): KotlinClassMetadata? = getMetadata()?.let(KotlinClassMetadata::readLenient)
|
||||||
return getMetadata()?.let(KotlinClassMetadata::readLenient)
|
|
||||||
}
|
|
||||||
|
|||||||
+2
-6
@@ -33,15 +33,13 @@ object KotlinUtils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getFieldGetterMethod(cls: ClassNode, field: FieldInfo): MethodNode? {
|
private fun getFieldGetterMethod(cls: ClassNode, field: FieldInfo): MethodNode? = cls.methods.firstOrNull {
|
||||||
return cls.methods.firstOrNull {
|
|
||||||
it.returnType == field.type &&
|
it.returnType == field.type &&
|
||||||
it.argTypes.isEmpty() &&
|
it.argTypes.isEmpty() &&
|
||||||
it.insnsCount == 3 &&
|
it.insnsCount == 3 &&
|
||||||
it.sVars.size == 2 &&
|
it.sVars.size == 2 &&
|
||||||
(it.sVars[1].assignInsn as? IndexInsnNode)?.index == field
|
(it.sVars[1].assignInsn as? IndexInsnNode)?.index == field
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private fun getGetterAlias(fieldAlias: String): String {
|
private fun getGetterAlias(fieldAlias: String): String {
|
||||||
val capitalized = fieldAlias.replaceFirstChar {
|
val capitalized = fieldAlias.replaceFirstChar {
|
||||||
@@ -84,7 +82,5 @@ object KotlinUtils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getDefaultMethodAlias(alias: String): String {
|
private fun getDefaultMethodAlias(alias: String): String = "$alias\$default"
|
||||||
return "$alias\$default"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-2
@@ -5,6 +5,5 @@ import org.slf4j.LoggerFactory
|
|||||||
|
|
||||||
inline val <reified T : Any> T.LOG: Logger get() = LoggerFactory.getLogger(T::class.java)
|
inline val <reified T : Any> T.LOG: Logger get() = LoggerFactory.getLogger(T::class.java)
|
||||||
|
|
||||||
inline fun <reified T : Any, R> T.runCatchingLog(msg: String? = null, block: () -> R) =
|
inline fun <reified T : Any, R> T.runCatchingLog(msg: String? = null, block: () -> R) = runCatching(block)
|
||||||
runCatching(block)
|
|
||||||
.onFailure { LOG.error(msg.orEmpty(), it) }
|
.onFailure { LOG.error(msg.orEmpty(), it) }
|
||||||
|
|||||||
+3
-9
@@ -124,23 +124,17 @@ class ToStringParser private constructor(mthToString: MethodNode) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun isStartStringBuilder(inst: InsnNode): Boolean {
|
private fun isStartStringBuilder(inst: InsnNode): Boolean = inst is ConstructorInsn &&
|
||||||
return inst is ConstructorInsn &&
|
|
||||||
inst.isNewInstance &&
|
inst.isNewInstance &&
|
||||||
inst.callMth.declClass.fullName == Consts.CLASS_STRING_BUILDER
|
inst.callMth.declClass.fullName == Consts.CLASS_STRING_BUILDER
|
||||||
}
|
|
||||||
|
|
||||||
private fun isAppendInvoke(inst: InsnNode): Boolean {
|
private fun isAppendInvoke(inst: InsnNode): Boolean = inst is InvokeNode &&
|
||||||
return inst is InvokeNode &&
|
|
||||||
inst.callMth.declClass.fullName == Consts.CLASS_STRING_BUILDER &&
|
inst.callMth.declClass.fullName == Consts.CLASS_STRING_BUILDER &&
|
||||||
inst.callMth.name == "append" &&
|
inst.callMth.name == "append" &&
|
||||||
inst.argsCount == 2
|
inst.argsCount == 2
|
||||||
}
|
|
||||||
|
|
||||||
private fun isToString(inst: InsnNode): Boolean {
|
private fun isToString(inst: InsnNode): Boolean = inst is InvokeNode &&
|
||||||
return inst is InvokeNode &&
|
|
||||||
inst.callMth.declClass.fullName == Consts.CLASS_STRING_BUILDER &&
|
inst.callMth.declClass.fullName == Consts.CLASS_STRING_BUILDER &&
|
||||||
inst.callMth.shortId == Consts.MTH_TOSTRING_SIGNATURE
|
inst.callMth.shortId == Consts.MTH_TOSTRING_SIGNATURE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|||||||
@@ -159,7 +159,6 @@ class TestKotlinMetadata : SmaliTest() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun assertThatClass(): JadxCodeAssertions =
|
private fun assertThatClass(): JadxCodeAssertions = assertThat(getClassNodeFromSmaliFiles("deobf", "TestKotlinMetadata", "a"))
|
||||||
assertThat(getClassNodeFromSmaliFiles("deobf", "TestKotlinMetadata", "a"))
|
|
||||||
.code()
|
.code()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,13 @@ plugins {
|
|||||||
dependencies {
|
dependencies {
|
||||||
api(project(":jadx-core"))
|
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")
|
testImplementation("org.apache.commons:commons-lang3:3.20.0")
|
||||||
|
|
||||||
testRuntimeOnly(project(":jadx-plugins:jadx-smali-input"))
|
testRuntimeOnly(project(":jadx-plugins:jadx-smali-input"))
|
||||||
|
|||||||
+1
-3
@@ -14,9 +14,7 @@ class KotlinSmapOptions : BasePluginOptionsBuilder() {
|
|||||||
.setter { isClassAliasSourceDbg = it }
|
.setter { isClassAliasSourceDbg = it }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun isClassSourceDbg(): Boolean {
|
fun isClassSourceDbg(): Boolean = isClassAliasSourceDbg
|
||||||
return isClassAliasSourceDbg
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val CLASS_ALIAS_SOURCE_DBG_OPT = "$PLUGIN_ID.class-alias-source-dbg"
|
const val CLASS_ALIAS_SOURCE_DBG_OPT = "$PLUGIN_ID.class-alias-source-dbg"
|
||||||
|
|||||||
+1
-3
@@ -9,9 +9,7 @@ class KotlinSmapPlugin : JadxPlugin {
|
|||||||
|
|
||||||
private val options = KotlinSmapOptions()
|
private val options = KotlinSmapOptions()
|
||||||
|
|
||||||
override fun getPluginInfo(): JadxPluginInfo {
|
override fun getPluginInfo(): JadxPluginInfo = JadxPluginInfo(PLUGIN_ID, "Kotlin SMAP", "Use kotlin.SourceDebugExtension annotation for rename class alias")
|
||||||
return JadxPluginInfo(PLUGIN_ID, "Kotlin SMAP", "Use kotlin.SourceDebugExtension annotation for rename class alias")
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun init(context: JadxPluginContext) {
|
override fun init(context: JadxPluginContext) {
|
||||||
context.registerOptions(options)
|
context.registerOptions(options)
|
||||||
|
|||||||
+7
-14
@@ -33,8 +33,7 @@ class SMAP(val fileMappings: List<FileMapping>) {
|
|||||||
class FileMapping(val name: String, val path: String) {
|
class FileMapping(val name: String, val path: String) {
|
||||||
val lineMappings = arrayListOf<RangeMapping>()
|
val lineMappings = arrayListOf<RangeMapping>()
|
||||||
|
|
||||||
fun toSourceInfo(): SourceInfo =
|
fun toSourceInfo(): SourceInfo = SourceInfo(
|
||||||
SourceInfo(
|
|
||||||
name,
|
name,
|
||||||
path,
|
path,
|
||||||
lineMappings.fold(0) { result, mapping -> max(result, mapping.source + mapping.range - 1) },
|
lineMappings.fold(0) { result, mapping -> max(result, mapping.source + mapping.range - 1) },
|
||||||
@@ -51,25 +50,19 @@ class FileMapping(val name: String, val path: String) {
|
|||||||
return mapping.mapSourceToDest(source)
|
return mapping.mapSourceToDest(source)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun RangeMapping.canReuseFor(newSource: Int, globalMaxDest: Int, newCallSite: SourcePosition?): Boolean =
|
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)
|
||||||
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 =
|
fun mapNewInterval(source: Int, dest: Int, range: Int, callSite: SourcePosition? = null): RangeMapping = RangeMapping(source, dest, range, callSite, parent = this).also { lineMappings.add(it) }
|
||||||
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) {
|
data class RangeMapping(val source: Int, val dest: Int, var range: Int, val callSite: SourcePosition?, val parent: FileMapping) {
|
||||||
operator fun contains(destLine: Int): Boolean =
|
operator fun contains(destLine: Int): Boolean = dest <= destLine && destLine < dest + range
|
||||||
dest <= destLine && destLine < dest + range
|
|
||||||
|
|
||||||
fun hasMappingForSource(sourceLine: Int): Boolean =
|
fun hasMappingForSource(sourceLine: Int): Boolean = source <= sourceLine && sourceLine < source + range
|
||||||
source <= sourceLine && sourceLine < source + range
|
|
||||||
|
|
||||||
fun mapDestToSource(destLine: Int): SourcePosition =
|
fun mapDestToSource(destLine: Int): SourcePosition = SourcePosition(source + (destLine - dest), parent.name, parent.path)
|
||||||
SourcePosition(source + (destLine - dest), parent.name, parent.path)
|
|
||||||
|
|
||||||
fun mapSourceToDest(sourceLine: Int): Int =
|
fun mapSourceToDest(sourceLine: Int): Int = dest + (sourceLine - source)
|
||||||
dest + (sourceLine - source)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val RangeMapping.toRange: IntRange
|
val RangeMapping.toRange: IntRange
|
||||||
|
|||||||
+1
-3
@@ -12,13 +12,11 @@ class KotlinSourceDebugExtensionPass(
|
|||||||
private val options: KotlinSmapOptions,
|
private val options: KotlinSmapOptions,
|
||||||
) : JadxPreparePass {
|
) : JadxPreparePass {
|
||||||
|
|
||||||
override fun getInfo(): JadxPassInfo {
|
override fun getInfo(): JadxPassInfo = OrderedJadxPassInfo(
|
||||||
return OrderedJadxPassInfo(
|
|
||||||
"SourceDebugExtensionPrepare",
|
"SourceDebugExtensionPrepare",
|
||||||
"Use kotlin.jvm.internal.SourceDebugExtension annotation to rename class & package",
|
"Use kotlin.jvm.internal.SourceDebugExtension annotation to rename class & package",
|
||||||
)
|
)
|
||||||
.before("RenameVisitor")
|
.before("RenameVisitor")
|
||||||
}
|
|
||||||
|
|
||||||
override fun init(root: RootNode) {
|
override fun init(root: RootNode) {
|
||||||
if (options.isClassAliasSourceDbg) {
|
if (options.isClassAliasSourceDbg) {
|
||||||
|
|||||||
+4
-5
@@ -22,8 +22,7 @@ import jadx.plugins.kotlin.smap.model.KOTLIN_STRATA_NAME
|
|||||||
import jadx.plugins.kotlin.smap.model.SMAP
|
import jadx.plugins.kotlin.smap.model.SMAP
|
||||||
|
|
||||||
object SMAPParser {
|
object SMAPParser {
|
||||||
fun parseOrNull(mappingInfo: String): SMAP? =
|
fun parseOrNull(mappingInfo: String): SMAP? = if (mappingInfo.isNotEmpty()) {
|
||||||
if (mappingInfo.isNotEmpty()) {
|
|
||||||
parseStratum(mappingInfo, KOTLIN_STRATA_NAME, parseStratum(mappingInfo, KOTLIN_DEBUG_STRATA_NAME, null))
|
parseStratum(mappingInfo, KOTLIN_STRATA_NAME, parseStratum(mappingInfo, KOTLIN_DEBUG_STRATA_NAME, null))
|
||||||
} else {
|
} else {
|
||||||
null
|
null
|
||||||
@@ -55,9 +54,7 @@ object SMAPParser {
|
|||||||
pos++
|
pos++
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun hasNext(): Boolean {
|
override fun hasNext(): Boolean = currentLine != null
|
||||||
return currentLine != null
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun next(): String {
|
override fun next(): String {
|
||||||
val res = currentLine ?: throw NoSuchElementException()
|
val res = currentLine ?: throw NoSuchElementException()
|
||||||
@@ -105,7 +102,9 @@ object SMAPParser {
|
|||||||
val range = when {
|
val range = when {
|
||||||
// These two fields have a different meaning, but for compatibility we treat them the same. See `SMAPBuilder`.
|
// 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()
|
destMultiplierSeparator != line.length -> line.substring(destMultiplierSeparator + 1).toInt()
|
||||||
|
|
||||||
sourceRangeSeparator != destSeparator -> line.substring(sourceRangeSeparator + 1, destSeparator).toInt()
|
sourceRangeSeparator != destSeparator -> line.substring(sourceRangeSeparator + 1, destSeparator).toInt()
|
||||||
|
|
||||||
else -> 1
|
else -> 1
|
||||||
}
|
}
|
||||||
// Here we assume that each range in `Kotlin` is entirely within at most one range in `KotlinDebug`.
|
// Here we assume that each range in `Kotlin` is entirely within at most one range in `KotlinDebug`.
|
||||||
|
|||||||
+1
-2
@@ -28,7 +28,6 @@ class TestSourceDebugExtension : SmaliTest() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun assertThatClass(): JadxCodeAssertions =
|
private fun assertThatClass(): JadxCodeAssertions = assertThat(getClassNodeFromSmaliFiles("deobf", "TestKotlinSourceDebugExtension", "C6"))
|
||||||
assertThat(getClassNodeFromSmaliFiles("deobf", "TestKotlinSourceDebugExtension", "C6"))
|
|
||||||
.code()
|
.code()
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user