From 661ebe439df59518a1af5538ed8234f4e395e6a6 Mon Sep 17 00:00:00 2001 From: Skylot Date: Tue, 11 May 2021 15:07:48 +0100 Subject: [PATCH] fix: inline class as anonymous if it used only once (#1168) --- jadx-core/src/main/java/jadx/core/Jadx.java | 2 +- .../core/dex/visitors/ProcessAnonymous.java | 30 +++++++++++++++++-- 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/jadx-core/src/main/java/jadx/core/Jadx.java b/jadx-core/src/main/java/jadx/core/Jadx.java index 516e818d6..ecfdc8e7f 100644 --- a/jadx-core/src/main/java/jadx/core/Jadx.java +++ b/jadx-core/src/main/java/jadx/core/Jadx.java @@ -85,9 +85,9 @@ public class Jadx { List passes = new ArrayList<>(); passes.add(new SignatureProcessor()); passes.add(new OverrideMethodVisitor()); - passes.add(new ProcessAnonymous()); passes.add(new RenameVisitor()); passes.add(new UsageInfoVisitor()); + passes.add(new ProcessAnonymous()); return passes; } diff --git a/jadx-core/src/main/java/jadx/core/dex/visitors/ProcessAnonymous.java b/jadx-core/src/main/java/jadx/core/dex/visitors/ProcessAnonymous.java index f4fcfb075..2e2385302 100644 --- a/jadx-core/src/main/java/jadx/core/dex/visitors/ProcessAnonymous.java +++ b/jadx-core/src/main/java/jadx/core/dex/visitors/ProcessAnonymous.java @@ -5,11 +5,15 @@ import jadx.core.dex.nodes.ClassNode; import jadx.core.dex.nodes.FieldNode; import jadx.core.dex.nodes.MethodNode; import jadx.core.dex.nodes.RootNode; +import jadx.core.dex.visitors.usage.UsageInfoVisitor; import jadx.core.utils.exceptions.JadxException; @JadxVisitor( name = "ProcessAnonymous", - desc = "Mark anonymous and lambda classes (for future inline)" + desc = "Mark anonymous and lambda classes (for future inline)", + runAfter = { + UsageInfoVisitor.class + } ) public class ProcessAnonymous extends AbstractVisitor { @@ -30,7 +34,7 @@ public class ProcessAnonymous extends AbstractVisitor { } private static void markAnonymousClass(ClassNode cls) { - if (isAnonymous(cls) || isLambdaCls(cls)) { + if (usedOnlyOnce(cls) || isAnonymous(cls) || isLambdaCls(cls)) { cls.add(AFlag.ANONYMOUS_CLASS); cls.add(AFlag.DONT_GENERATE); @@ -42,6 +46,28 @@ public class ProcessAnonymous extends AbstractVisitor { } } + private static boolean usedOnlyOnce(ClassNode cls) { + if (cls.getUseIn().size() == 1 && cls.getUseInMth().size() == 1) { + // used only once + boolean synthetic = cls.getAccessFlags().isSynthetic() || cls.getClassInfo().getShortName().contains("$"); + if (synthetic) { + // must have only one constructor which used only once + MethodNode ctr = null; + for (MethodNode mth : cls.getMethods()) { + if (mth.isConstructor()) { + if (ctr != null) { + ctr = null; + break; + } + ctr = mth; + } + } + return ctr != null && ctr.getUseIn().size() == 1; + } + } + return false; + } + private static boolean isAnonymous(ClassNode cls) { return cls.getClassInfo().isInner() && Character.isDigit(cls.getClassInfo().getShortName().charAt(0))