Commit 7654661b authored by Skylot's avatar Skylot

fix: inline desugared lambda classes (#467)

parent 51a9c741
...@@ -17,7 +17,6 @@ import org.slf4j.LoggerFactory; ...@@ -17,7 +17,6 @@ import org.slf4j.LoggerFactory;
import jadx.core.Jadx; import jadx.core.Jadx;
import jadx.core.ProcessClass; import jadx.core.ProcessClass;
import jadx.core.codegen.CodeGen;
import jadx.core.dex.attributes.AFlag; import jadx.core.dex.attributes.AFlag;
import jadx.core.dex.nodes.ClassNode; import jadx.core.dex.nodes.ClassNode;
import jadx.core.dex.nodes.FieldNode; import jadx.core.dex.nodes.FieldNode;
...@@ -59,7 +58,6 @@ public final class JadxDecompiler { ...@@ -59,7 +58,6 @@ public final class JadxDecompiler {
private RootNode root; private RootNode root;
private List<IDexTreeVisitor> passes; private List<IDexTreeVisitor> passes;
private CodeGen codeGen;
private List<JavaClass> classes; private List<JavaClass> classes;
private List<ResourceFile> resources; private List<ResourceFile> resources;
...@@ -97,7 +95,6 @@ public final class JadxDecompiler { ...@@ -97,7 +95,6 @@ public final class JadxDecompiler {
void init() { void init() {
this.passes = Jadx.getPassesList(args); this.passes = Jadx.getPassesList(args);
this.codeGen = new CodeGen();
} }
void reset() { void reset() {
...@@ -106,7 +103,6 @@ public final class JadxDecompiler { ...@@ -106,7 +103,6 @@ public final class JadxDecompiler {
xmlParser = null; xmlParser = null;
root = null; root = null;
passes = null; passes = null;
codeGen = null;
} }
public static String getVersion() { public static String getVersion() {
...@@ -215,10 +211,12 @@ public final class JadxDecompiler { ...@@ -215,10 +211,12 @@ public final class JadxDecompiler {
List<JavaClass> clsList = new ArrayList<>(classNodeList.size()); List<JavaClass> clsList = new ArrayList<>(classNodeList.size());
classesMap.clear(); classesMap.clear();
for (ClassNode classNode : classNodeList) { for (ClassNode classNode : classNodeList) {
if (!classNode.contains(AFlag.DONT_GENERATE)) {
JavaClass javaClass = new JavaClass(classNode, this); JavaClass javaClass = new JavaClass(classNode, this);
clsList.add(javaClass); clsList.add(javaClass);
classesMap.put(classNode, javaClass); classesMap.put(classNode, javaClass);
} }
}
classes = Collections.unmodifiableList(clsList); classes = Collections.unmodifiableList(clsList);
} }
return classes; return classes;
...@@ -289,7 +287,7 @@ public final class JadxDecompiler { ...@@ -289,7 +287,7 @@ public final class JadxDecompiler {
} }
void processClass(ClassNode cls) { void processClass(ClassNode cls) {
ProcessClass.process(cls, passes, codeGen); ProcessClass.process(cls, passes, true);
} }
RootNode getRoot() { RootNode getRoot() {
......
...@@ -2,8 +2,6 @@ package jadx.core; ...@@ -2,8 +2,6 @@ package jadx.core;
import java.util.List; import java.util.List;
import org.jetbrains.annotations.Nullable;
import jadx.core.codegen.CodeGen; import jadx.core.codegen.CodeGen;
import jadx.core.dex.nodes.ClassNode; import jadx.core.dex.nodes.ClassNode;
import jadx.core.dex.visitors.DepthTraversal; import jadx.core.dex.visitors.DepthTraversal;
...@@ -19,8 +17,8 @@ public final class ProcessClass { ...@@ -19,8 +17,8 @@ public final class ProcessClass {
private ProcessClass() { private ProcessClass() {
} }
public static void process(ClassNode cls, List<IDexTreeVisitor> passes, @Nullable CodeGen codeGen) { public static void process(ClassNode cls, List<IDexTreeVisitor> passes, boolean generateCode) {
if (codeGen == null && cls.getState() == PROCESSED) { if (!generateCode && cls.getState() == PROCESSED) {
return; return;
} }
synchronized (getSyncObj(cls)) { synchronized (getSyncObj(cls)) {
...@@ -33,9 +31,9 @@ public final class ProcessClass { ...@@ -33,9 +31,9 @@ public final class ProcessClass {
} }
cls.setState(PROCESSED); cls.setState(PROCESSED);
} }
if (cls.getState() == PROCESSED && codeGen != null) { if (cls.getState() == PROCESSED && generateCode) {
processDependencies(cls, passes); processDependencies(cls, passes);
codeGen.visit(cls); CodeGen.generate(cls);
} }
} catch (Exception e) { } catch (Exception e) {
ErrorsCounter.classError(cls, e.getClass().getSimpleName(), e); ErrorsCounter.classError(cls, e.getClass().getSimpleName(), e);
...@@ -48,6 +46,6 @@ public final class ProcessClass { ...@@ -48,6 +46,6 @@ public final class ProcessClass {
} }
private static void processDependencies(ClassNode cls, List<IDexTreeVisitor> passes) { private static void processDependencies(ClassNode cls, List<IDexTreeVisitor> passes) {
cls.getDependencies().forEach(depCls -> process(depCls, passes, null)); cls.getDependencies().forEach(depCls -> process(depCls, passes, false));
} }
} }
...@@ -98,7 +98,7 @@ public class ClassGen { ...@@ -98,7 +98,7 @@ public class ClassGen {
imports.clear(); imports.clear();
} }
clsCode.add(clsBody); clsCode.add(clsBody);
return clsCode; return clsCode.finish();
} }
public void addClassCode(CodeWriter code) throws CodegenException { public void addClassCode(CodeWriter code) throws CodegenException {
......
package jadx.core.codegen; package jadx.core.codegen;
import jadx.core.dex.attributes.AFlag;
import jadx.core.dex.nodes.ClassNode; import jadx.core.dex.nodes.ClassNode;
import jadx.core.utils.exceptions.CodegenException; import jadx.core.utils.exceptions.CodegenException;
public class CodeGen { public class CodeGen {
public boolean visit(ClassNode cls) throws CodegenException { public static void generate(ClassNode cls) throws CodegenException {
if (cls.contains(AFlag.DONT_GENERATE)) {
cls.setCode(CodeWriter.EMPTY);
} else {
ClassGen clsGen = new ClassGen(cls, cls.root().getArgs()); ClassGen clsGen = new ClassGen(cls, cls.root().getArgs());
CodeWriter clsCode = clsGen.makeClass(); cls.setCode(clsGen.makeClass());
clsCode.finish(); }
cls.setCode(clsCode); }
return false;
private CodeGen() {
} }
} }
...@@ -24,6 +24,8 @@ public class CodeWriter { ...@@ -24,6 +24,8 @@ public class CodeWriter {
public static final String NL = System.getProperty("line.separator"); public static final String NL = System.getProperty("line.separator");
public static final String INDENT_STR = " "; public static final String INDENT_STR = " ";
public static final CodeWriter EMPTY = new CodeWriter().finish();
private static final boolean ADD_LINE_NUMBERS = false; private static final boolean ADD_LINE_NUMBERS = false;
private static final String[] INDENT_CACHE = { private static final String[] INDENT_CACHE = {
...@@ -250,7 +252,7 @@ public class CodeWriter { ...@@ -250,7 +252,7 @@ public class CodeWriter {
return lineMap; return lineMap;
} }
public void finish() { public CodeWriter finish() {
removeFirstEmptyLine(); removeFirstEmptyLine();
buf.trimToSize(); buf.trimToSize();
code = buf.toString(); code = buf.toString();
...@@ -266,11 +268,12 @@ public class CodeWriter { ...@@ -266,11 +268,12 @@ public class CodeWriter {
it.remove(); it.remove();
} }
} }
return this;
} }
private void removeFirstEmptyLine() { private void removeFirstEmptyLine() {
int len = NL.length(); int len = NL.length();
if (buf.substring(0, len).equals(NL)) { if (buf.length() > len && buf.substring(0, len).equals(NL)) {
buf.delete(0, len); buf.delete(0, len);
} }
} }
......
...@@ -48,7 +48,6 @@ import jadx.core.dex.nodes.FieldNode; ...@@ -48,7 +48,6 @@ import jadx.core.dex.nodes.FieldNode;
import jadx.core.dex.nodes.InsnNode; import jadx.core.dex.nodes.InsnNode;
import jadx.core.dex.nodes.MethodNode; import jadx.core.dex.nodes.MethodNode;
import jadx.core.dex.nodes.RootNode; import jadx.core.dex.nodes.RootNode;
import jadx.core.utils.ErrorsCounter;
import jadx.core.utils.RegionUtils; import jadx.core.utils.RegionUtils;
import jadx.core.utils.exceptions.CodegenException; import jadx.core.utils.exceptions.CodegenException;
import jadx.core.utils.exceptions.JadxRuntimeException; import jadx.core.utils.exceptions.JadxRuntimeException;
...@@ -559,7 +558,7 @@ public class InsnGen { ...@@ -559,7 +558,7 @@ public class InsnGen {
throws CodegenException { throws CodegenException {
ClassNode cls = mth.dex().resolveClass(insn.getClassType()); ClassNode cls = mth.dex().resolveClass(insn.getClassType());
if (cls != null && cls.contains(AFlag.ANONYMOUS_CLASS) && !fallback) { if (cls != null && cls.contains(AFlag.ANONYMOUS_CLASS) && !fallback) {
inlineAnonymousConstr(code, cls, insn); inlineAnonymousConstructor(code, cls, insn);
return; return;
} }
if (insn.isSelf()) { if (insn.isSelf()) {
...@@ -577,20 +576,14 @@ public class InsnGen { ...@@ -577,20 +576,14 @@ public class InsnGen {
generateMethodArguments(code, insn, 0, callMth); generateMethodArguments(code, insn, 0, callMth);
} }
private void inlineAnonymousConstr(CodeWriter code, ClassNode cls, ConstructorInsn insn) throws CodegenException { private void inlineAnonymousConstructor(CodeWriter code, ClassNode cls, ConstructorInsn insn) throws CodegenException {
// anonymous class construction cls.add(AFlag.DONT_GENERATE);
if (cls.contains(AFlag.DONT_GENERATE)) {
code.add("/* anonymous class already generated */");
ErrorsCounter.methodWarn(mth, "Anonymous class already generated: " + cls);
return;
}
ArgType parent; ArgType parent;
if (cls.getInterfaces().size() == 1) { if (cls.getInterfaces().size() == 1) {
parent = cls.getInterfaces().get(0); parent = cls.getInterfaces().get(0);
} else { } else {
parent = cls.getSuperClass(); parent = cls.getSuperClass();
} }
cls.add(AFlag.DONT_GENERATE);
MethodNode defCtr = cls.getDefaultConstructor(); MethodNode defCtr = cls.getDefaultConstructor();
if (defCtr != null) { if (defCtr != null) {
if (RegionUtils.notEmpty(defCtr.getRegion())) { if (RegionUtils.notEmpty(defCtr.getRegion())) {
......
...@@ -19,6 +19,7 @@ import org.slf4j.LoggerFactory; ...@@ -19,6 +19,7 @@ import org.slf4j.LoggerFactory;
import jadx.core.Consts; import jadx.core.Consts;
import jadx.core.codegen.CodeWriter; import jadx.core.codegen.CodeWriter;
import jadx.core.dex.attributes.AFlag;
import jadx.core.dex.attributes.annotations.Annotation; import jadx.core.dex.attributes.annotations.Annotation;
import jadx.core.dex.attributes.nodes.LineAttrNode; import jadx.core.dex.attributes.nodes.LineAttrNode;
import jadx.core.dex.attributes.nodes.SourceFileAttr; import jadx.core.dex.attributes.nodes.SourceFileAttr;
...@@ -123,7 +124,7 @@ public class ClassNode extends LineAttrNode implements ILoadable, ICodeNode { ...@@ -123,7 +124,7 @@ public class ClassNode extends LineAttrNode implements ILoadable, ICodeNode {
accFlagsValue = cls.getAccessFlags(); accFlagsValue = cls.getAccessFlags();
} }
this.accessFlags = new AccessInfo(accFlagsValue, AFType.CLASS); this.accessFlags = new AccessInfo(accFlagsValue, AFType.CLASS);
markAnonymousClass(this);
buildCache(); buildCache();
} catch (Exception e) { } catch (Exception e) {
throw new JadxRuntimeException("Error decode class: " + clsInfo, e); throw new JadxRuntimeException("Error decode class: " + clsInfo, e);
...@@ -394,6 +395,29 @@ public class ClassNode extends LineAttrNode implements ILoadable, ICodeNode { ...@@ -394,6 +395,29 @@ public class ClassNode extends LineAttrNode implements ILoadable, ICodeNode {
&& getDefaultConstructor() != null; && getDefaultConstructor() != null;
} }
public boolean isLambdaCls() {
return accessFlags.isSynthetic() && accessFlags.isFinal()
&& clsInfo.getType().getObject().contains(".-$$Lambda$")
&& countStaticFields() == 0;
}
private int countStaticFields() {
int c = 0;
for (FieldNode field : fields) {
if (field.getAccessFlags().isStatic()) {
c++;
}
}
return c;
}
private static void markAnonymousClass(ClassNode cls) {
if (cls.isAnonymous() || cls.isLambdaCls()) {
cls.add(AFlag.ANONYMOUS_CLASS);
cls.add(AFlag.DONT_GENERATE);
}
}
@Nullable @Nullable
public MethodNode getClassInitMth() { public MethodNode getClassInitMth() {
return searchMethodByName("<clinit>()V"); return searchMethodByName("<clinit>()V");
......
...@@ -54,31 +54,36 @@ public class ClassModifier extends AbstractVisitor { ...@@ -54,31 +54,36 @@ public class ClassModifier extends AbstractVisitor {
cls.add(AFlag.DONT_GENERATE); cls.add(AFlag.DONT_GENERATE);
return false; return false;
} }
markAnonymousClass(cls);
removeSyntheticFields(cls); removeSyntheticFields(cls);
cls.getMethods().forEach(mth -> removeSyntheticMethods(cls, mth)); cls.getMethods().forEach(ClassModifier::removeSyntheticMethods);
cls.getMethods().forEach(ClassModifier::removeEmptyMethods); cls.getMethods().forEach(ClassModifier::removeEmptyMethods);
markAnonymousClass(cls);
return false; return false;
} }
private void markAnonymousClass(ClassNode cls) { private void markAnonymousClass(ClassNode cls) {
if (cls.isAnonymous()) { if (cls.isAnonymous()) {
cls.add(AFlag.ANONYMOUS_CLASS); cls.add(AFlag.ANONYMOUS_CLASS);
cls.add(AFlag.DONT_GENERATE);
} }
} }
/**
* Remove synthetic fields if type is outer class or class will be inlined (anonymous)
*/
private static void removeSyntheticFields(ClassNode cls) { private static void removeSyntheticFields(ClassNode cls) {
if (!cls.getClassInfo().isInner() || cls.getAccessFlags().isStatic()) { if (cls.getAccessFlags().isStatic()) {
return; return;
} }
// remove fields if it is synthetic and type is a outer class boolean inline = cls.contains(AFlag.ANONYMOUS_CLASS);
if (inline || cls.getClassInfo().isInner()) {
for (FieldNode field : cls.getFields()) { for (FieldNode field : cls.getFields()) {
if (field.getAccessFlags().isSynthetic() && field.getType().isObject()) { if (field.getAccessFlags().isSynthetic() && field.getType().isObject()) {
ClassInfo clsInfo = ClassInfo.fromType(cls.root(), field.getType()); ClassInfo clsInfo = ClassInfo.fromType(cls.root(), field.getType());
ClassNode fieldsCls = cls.dex().resolveClass(clsInfo); ClassNode fieldsCls = cls.dex().resolveClass(clsInfo);
ClassInfo parentClass = cls.getClassInfo().getParentClass(); ClassInfo parentClass = cls.getClassInfo().getParentClass();
if (fieldsCls != null && parentClass.equals(fieldsCls.getClassInfo())) { if (fieldsCls != null
&& (inline || parentClass.equals(fieldsCls.getClassInfo()))) {
int found = 0; int found = 0;
for (MethodNode mth : cls.getMethods()) { for (MethodNode mth : cls.getMethods()) {
if (removeFieldUsageFromConstructor(mth, field, fieldsCls)) { if (removeFieldUsageFromConstructor(mth, field, fieldsCls)) {
...@@ -86,13 +91,14 @@ public class ClassModifier extends AbstractVisitor { ...@@ -86,13 +91,14 @@ public class ClassModifier extends AbstractVisitor {
} }
} }
if (found != 0) { if (found != 0) {
field.addAttr(new FieldReplaceAttr(parentClass)); field.addAttr(new FieldReplaceAttr(fieldsCls.getClassInfo()));
field.add(AFlag.DONT_GENERATE); field.add(AFlag.DONT_GENERATE);
} }
} }
} }
} }
} }
}
private static boolean removeFieldUsageFromConstructor(MethodNode mth, FieldNode field, ClassNode fieldsCls) { private static boolean removeFieldUsageFromConstructor(MethodNode mth, FieldNode field, ClassNode fieldsCls) {
if (mth.isNoCode() || !mth.getAccessFlags().isConstructor()) { if (mth.isNoCode() || !mth.getAccessFlags().isConstructor()) {
...@@ -133,7 +139,7 @@ public class ClassModifier extends AbstractVisitor { ...@@ -133,7 +139,7 @@ public class ClassModifier extends AbstractVisitor {
return true; return true;
} }
private static void removeSyntheticMethods(ClassNode cls, MethodNode mth) { private static void removeSyntheticMethods(MethodNode mth) {
if (mth.isNoCode()) { if (mth.isNoCode()) {
return; return;
} }
...@@ -141,6 +147,7 @@ public class ClassModifier extends AbstractVisitor { ...@@ -141,6 +147,7 @@ public class ClassModifier extends AbstractVisitor {
if (!af.isSynthetic()) { if (!af.isSynthetic()) {
return; return;
} }
ClassNode cls = mth.getParentClass();
if (removeBridgeMethod(cls, mth)) { if (removeBridgeMethod(cls, mth)) {
if (Consts.DEBUG) { if (Consts.DEBUG) {
mth.addAttr(AType.COMMENTS, "Removed as synthetic bridge method"); mth.addAttr(AType.COMMENTS, "Removed as synthetic bridge method");
......
...@@ -11,6 +11,7 @@ import jadx.core.dex.instructions.args.ArgType; ...@@ -11,6 +11,7 @@ import jadx.core.dex.instructions.args.ArgType;
import jadx.core.dex.instructions.args.InsnArg; import jadx.core.dex.instructions.args.InsnArg;
import jadx.core.dex.instructions.args.InsnWrapArg; import jadx.core.dex.instructions.args.InsnWrapArg;
import jadx.core.dex.instructions.args.RegisterArg; import jadx.core.dex.instructions.args.RegisterArg;
import jadx.core.dex.instructions.mods.ConstructorInsn;
import jadx.core.dex.nodes.BlockNode; import jadx.core.dex.nodes.BlockNode;
import jadx.core.dex.nodes.ClassNode; import jadx.core.dex.nodes.ClassNode;
import jadx.core.dex.nodes.DexNode; import jadx.core.dex.nodes.DexNode;
...@@ -90,6 +91,9 @@ public class DependencyCollector extends AbstractVisitor { ...@@ -90,6 +91,9 @@ public class DependencyCollector extends AbstractVisitor {
} else if (insn instanceof InvokeNode) { } else if (insn instanceof InvokeNode) {
ClassInfo declClass = ((InvokeNode) insn).getCallMth().getDeclClass(); ClassInfo declClass = ((InvokeNode) insn).getCallMth().getDeclClass();
addDep(dex, depList, declClass); addDep(dex, depList, declClass);
} else if (insn instanceof ConstructorInsn) {
ClassInfo declClass = ((ConstructorInsn) insn).getCallMth().getDeclClass();
addDep(dex, depList, declClass);
} }
} }
......
...@@ -5,6 +5,8 @@ import java.util.Collections; ...@@ -5,6 +5,8 @@ import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import org.jetbrains.annotations.Nullable;
import jadx.core.dex.attributes.AType; import jadx.core.dex.attributes.AType;
import jadx.core.dex.instructions.InsnType; import jadx.core.dex.instructions.InsnType;
import jadx.core.dex.nodes.BlockNode; import jadx.core.dex.nodes.BlockNode;
...@@ -136,7 +138,10 @@ public class RegionUtils { ...@@ -136,7 +138,10 @@ public class RegionUtils {
return !notEmpty(container); return !notEmpty(container);
} }
public static boolean notEmpty(IContainer container) { public static boolean notEmpty(@Nullable IContainer container) {
if (container == null) {
return false;
}
if (container instanceof IBlock) { if (container instanceof IBlock) {
return !((IBlock) container).getInstructions().isEmpty(); return !((IBlock) container).getInstructions().isEmpty();
} else if (container instanceof IRegion) { } else if (container instanceof IRegion) {
......
...@@ -139,7 +139,7 @@ public abstract class IntegrationTest extends TestUtils { ...@@ -139,7 +139,7 @@ public abstract class IntegrationTest extends TestUtils {
protected void decompile(JadxDecompiler jadx, ClassNode cls) { protected void decompile(JadxDecompiler jadx, ClassNode cls) {
List<IDexTreeVisitor> passes = getPassesList(jadx); List<IDexTreeVisitor> passes = getPassesList(jadx);
ProcessClass.process(cls, passes, new CodeGen()); ProcessClass.process(cls, passes, true);
} }
protected void decompileWithoutUnload(JadxDecompiler jadx, ClassNode cls) { protected void decompileWithoutUnload(JadxDecompiler jadx, ClassNode cls) {
...@@ -168,7 +168,7 @@ public abstract class IntegrationTest extends TestUtils { ...@@ -168,7 +168,7 @@ public abstract class IntegrationTest extends TestUtils {
protected void generateClsCode(ClassNode cls) { protected void generateClsCode(ClassNode cls) {
try { try {
new CodeGen().visit(cls); CodeGen.generate(cls);
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
fail(e.getMessage()); fail(e.getMessage());
......
...@@ -15,12 +15,11 @@ import jadx.api.JadxDecompiler; ...@@ -15,12 +15,11 @@ import jadx.api.JadxDecompiler;
import jadx.api.JadxInternalAccess; import jadx.api.JadxInternalAccess;
import jadx.api.JavaClass; import jadx.api.JavaClass;
import jadx.core.Jadx; import jadx.core.Jadx;
import jadx.core.codegen.CodeGen; import jadx.core.ProcessClass;
import jadx.core.codegen.CodeWriter; import jadx.core.codegen.CodeWriter;
import jadx.core.dex.nodes.ClassNode; import jadx.core.dex.nodes.ClassNode;
import jadx.core.dex.nodes.MethodNode; import jadx.core.dex.nodes.MethodNode;
import jadx.core.dex.nodes.RootNode; import jadx.core.dex.nodes.RootNode;
import jadx.core.dex.visitors.DepthTraversal;
import jadx.core.dex.visitors.IDexTreeVisitor; import jadx.core.dex.visitors.IDexTreeVisitor;
import jadx.core.utils.exceptions.JadxRuntimeException; import jadx.core.utils.exceptions.JadxRuntimeException;
import jadx.tests.api.IntegrationTest; import jadx.tests.api.IntegrationTest;
...@@ -77,7 +76,7 @@ public abstract class BaseExternalTest extends IntegrationTest { ...@@ -77,7 +76,7 @@ public abstract class BaseExternalTest extends IntegrationTest {
for (ClassNode classNode : root.getClasses(true)) { for (ClassNode classNode : root.getClasses(true)) {
String clsFullName = classNode.getClassInfo().getFullName(); String clsFullName = classNode.getClassInfo().getFullName();
if (clsPattern.matcher(clsFullName).matches()) { if (clsPattern.matcher(clsFullName).matches()) {
if (processCls(mthPattern, passes, classNode)) { if (processCls(jadx, mthPattern, passes, classNode)) {
processed++; processed++;
} }
} }
...@@ -85,7 +84,7 @@ public abstract class BaseExternalTest extends IntegrationTest { ...@@ -85,7 +84,7 @@ public abstract class BaseExternalTest extends IntegrationTest {
assertThat("No classes processed", processed, greaterThan(0)); assertThat("No classes processed", processed, greaterThan(0));
} }
private boolean processCls(@Nullable Pattern mthPattern, List<IDexTreeVisitor> passes, ClassNode classNode) { private boolean processCls(JadxDecompiler jadx, @Nullable Pattern mthPattern, List<IDexTreeVisitor> passes, ClassNode classNode) {
classNode.load(); classNode.load();
boolean decompile = false; boolean decompile = false;
if (mthPattern == null) { if (mthPattern == null) {
...@@ -101,11 +100,8 @@ public abstract class BaseExternalTest extends IntegrationTest { ...@@ -101,11 +100,8 @@ public abstract class BaseExternalTest extends IntegrationTest {
if (!decompile) { if (!decompile) {
return false; return false;
} }
for (IDexTreeVisitor visitor : passes) {
DepthTraversal.visit(visitor, classNode);
}
try { try {
new CodeGen().visit(classNode); ProcessClass.process(classNode, passes, true);
} catch (Exception e) { } catch (Exception e) {
throw new JadxRuntimeException("Codegen failed", e); throw new JadxRuntimeException("Codegen failed", e);
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment