main.jadx.plugins.kotlin.metadata.utils.KotlinUtils.kt Maven / Gradle / Ivy
The newest version!
package jadx.plugins.kotlin.metadata.utils
import jadx.core.Consts
import jadx.core.dex.info.FieldInfo
import jadx.core.dex.instructions.IndexInsnNode
import jadx.core.dex.instructions.InsnType
import jadx.core.dex.instructions.InvokeNode
import jadx.core.dex.instructions.args.PrimitiveType
import jadx.core.dex.nodes.ClassNode
import jadx.core.dex.nodes.FieldNode
import jadx.core.dex.nodes.MethodNode
import jadx.plugins.kotlin.metadata.model.MethodRename
import jadx.plugins.kotlin.metadata.model.ToStringRename
import java.util.Locale
object KotlinUtils {
fun parseToString(cls: ClassNode): ToStringRename? {
val mthToString = cls.searchMethodByShortId(Consts.MTH_TOSTRING_SIGNATURE)
?: return null
return ToStringParser.parse(mthToString)
}
fun findGetters(cls: ClassNode): List {
return cls.fields.filter(FieldNode::isInstance).mapNotNull { field ->
val mth = getFieldGetterMethod(cls, field.fieldInfo)
?: return@mapNotNull null
MethodRename(
mth = mth,
alias = getGetterAlias(field.alias),
)
}
}
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 getGetterAlias(fieldAlias: String): String {
val capitalized = fieldAlias.replaceFirstChar {
if (it.isLowerCase()) it.titlecase(Locale.ROOT) else it.toString()
}
return "get$capitalized"
}
// untested & overly complicated
fun parseDefaultMethods(cls: ClassNode): List {
val possibleMthList = cls.methods.filter {
it.accessFlags.isStatic && it.accessFlags.isSynthetic &&
it.argTypes.run {
size > 3 &&
first().isObject && first().`object` == cls.fullName &&
get(size - 2).isPrimitive && get(size - 2).primitiveType == PrimitiveType.INT &&
last().isObject && last().`object` == Consts.CLASS_OBJECT
}
}
val insnList = possibleMthList.filter {
it.exitBlock.run {
iDom != null && iDom.instructions.firstOrNull()?.type == InsnType.RETURN
iDom.iDom != null
} &&
it.exitBlock.iDom.iDom.run {
instructions.firstOrNull() is InvokeNode
}
}
val remapped = insnList.mapNotNull {
val insn = it.exitBlock.iDom.iDom.instructions.first() as InvokeNode
cls.searchMethodByShortId(insn.callMth.shortId)?.run { it to this }
}
return remapped.map { (defaultMethod, originalMethod) ->
MethodRename(
mth = defaultMethod,
alias = getDefaultMethodAlias(originalMethod.alias),
)
}
}
private fun getDefaultMethodAlias(alias: String): String {
return "$alias\$default"
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy