skylot / jadx

Dex to Java decompiler
Apache License 2.0
41.81k stars 4.88k forks source link

[core] Kotlin - Undefined parametrized types #1800

Closed bagipro closed 1 year ago

bagipro commented 1 year ago

Hey!

APK: https://drive.google.com/file/d/1NEIPWFwukzv1BgJDHpaqKZAznMf25lqW/view?usp=sharing

Jadx generates a lot of type declarations without specifying parametrized types, such as kotlin.sequences.SequencesKt___SequencesKt$zipWithNext$1:

public final class SequencesKt___SequencesKt$zipWithNext$1 extends kotlin.jvm.internal.Lambda implements kotlin.jvm.functions.Function2<T, T, kotlin.Tuples<? extends T, ? extends T>> {
    public static final kotlin.sequences.SequencesKt___SequencesKt$zipWithNext$1 INSTANCE = new kotlin.sequences.SequencesKt___SequencesKt$zipWithNext$1();

    public SequencesKt___SequencesKt$zipWithNext$1() {
        super(2);
    }

    @Override
    @org.jetbrains.annotations.NotNull
    public final kotlin.Tuples<T, T> invoke(T t, T t2) {
        return kotlin.TuplesKt.to(t, t2);
    }
}

Another example is in class androidx.collection.SparseArrayKt$keyIterator$1:

public final class SparseArrayKt$keyIterator$1 extends kotlin.collections.IntIterator {
    final androidx.collection.SparseArrayCompat $this_keyIterator;
    private int index;

    public SparseArrayKt$keyIterator$1(androidx.collection.SparseArrayCompat<T> sparseArrayCompat) {
        this.$this_keyIterator = sparseArrayCompat;
    }

All T types here are undefined. It breaks all code logic such as inherited methods

skylot commented 1 year ago

@bagipro looks like this class should be inlined and use outer method generic. But because this lambda used by instance field, inline not yet supported, this mentioned in #523. I will increase priority of this case. Another issue: if class inlining is disabled or not possible, jadx needs to ignore unknown generics to make resulting code correct, this should be fixed also.

skylot commented 1 year ago

@bagipro I commit a fix for second issue: add missing type parameter declarations, code should be correct now :slightly_smiling_face:

skylot commented 1 year ago

Ok, I implement class inlining by instance field :tada: Although for Kotlin lambdas it changes code semantic by removing extend of kotlin.jvm.internal.Lambda class, this class hold arity property and used somewhere in Kotlin runtime. After some checks I think it is safe to perform inline, but just in case I add option to disable of inling Kotlin lambdas: --no-inline-kotlin-lambda in cli and Allow to inline Kotlin Lambdas in gui.