Skip to content

Commit

Permalink
fix: invoke in nested anonymous classes (#1305)
Browse files Browse the repository at this point in the history
  • Loading branch information
skylot committed Dec 12, 2021
1 parent 9c446eb commit d2bde0b
Show file tree
Hide file tree
Showing 5 changed files with 104 additions and 3 deletions.
17 changes: 15 additions & 2 deletions jadx-core/src/main/java/jadx/core/codegen/InsnGen.java
Original file line number Diff line number Diff line change
Expand Up @@ -763,8 +763,7 @@ private void makeInvoke(InvokeNode insn, ICodeWriter code) throws CodegenExcepti
case VIRTUAL:
case INTERFACE:
InsnArg arg = insn.getArg(0);
// FIXME: add 'this' for equals methods in scope
if (!arg.isThis()) {
if (needInvokeArg(arg)) {
addArgDot(code, arg);
}
k++;
Expand Down Expand Up @@ -799,6 +798,20 @@ private void makeInvoke(InvokeNode insn, ICodeWriter code) throws CodegenExcepti
generateMethodArguments(code, insn, k, callMthNode);
}

// FIXME: add 'this' for equals methods in scope
private boolean needInvokeArg(InsnArg arg) {
if (arg.isAnyThis()) {
if (arg.isThis()) {
return false;
}
ClassNode clsNode = mth.root().resolveClass(arg.getType());
if (clsNode != null && clsNode.contains(AFlag.DONT_GENERATE)) {
return false;
}
}
return true;
}

private void makeInvokeLambda(ICodeWriter code, InvokeCustomNode customNode) throws CodegenException {
if (customNode.isUseRef()) {
makeRefLambda(code, customNode);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,27 @@ public boolean isThis() {
return contains(AFlag.THIS);
}

/**
* Return true for 'this' from other classes (often occur in anonymous classes)
*/
public boolean isAnyThis() {
if (contains(AFlag.THIS)) {
return true;
}
InsnNode wrappedInsn = unwrap();
if (wrappedInsn != null && wrappedInsn.getType() == InsnType.IGET) {
return wrappedInsn.getArg(0).isAnyThis();
}
return false;
}

public InsnNode unwrap() {
if (isInsnWrap()) {
return ((InsnWrapArg) this).getWrapInsn();
}
return null;
}

public boolean isConst() {
return isLiteral() || (isInsnWrap() && ((InsnWrapArg) this).getWrapInsn().isConstInsn());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ private static void checkClassName(Deobfuscator deobfuscator, ClassNode cls, Jad
// check inner classes names
ClassInfo parentClass = classInfo.getParentClass();
while (parentClass != null) {
if (parentClass.getAliasShortName().equals(clsName)) {
if (parentClass.getAliasShortName().equals(newShortName)) {
String clsAlias = deobfuscator.getClsAlias(cls);
classInfo.changeShortName(clsAlias);
cls.addAttr(new RenameReasonAttr(cls).append("collision with other inner class name"));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,13 @@ public JadxCodeAssertions removeBlockComments() {
return newCode;
}

public JadxCodeAssertions removeLineComments() {
String code = actual.replaceAll("//.*(?!$)", "");
JadxCodeAssertions newCode = new JadxCodeAssertions(code);
newCode.print();
return newCode;
}

public JadxCodeAssertions print() {
System.out.println("-----------------------------------------------------------");
System.out.println(actual);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package jadx.tests.integration.inner;

import org.junit.jupiter.api.Test;

import jadx.api.CommentsLevel;
import jadx.tests.api.IntegrationTest;

import static jadx.tests.api.utils.assertj.JadxAssertions.assertThat;

public class TestAnonymousClass18 extends IntegrationTest {

@SuppressWarnings({ "Convert2Lambda", "Anonymous2MethodRef", "unused" })
public static class TestCls {

public interface Job {
void executeJob();
}

public void start() {
runJob(new Job() {
@Override
public void executeJob() {
runJob(new Job() {
@Override
public void executeJob() {
doSomething();
}
});
}

private void doSomething() {
}
});
}

public static void runJob(Job job) {
}
}

@Test
public void test() {
getArgs().setCommentsLevel(CommentsLevel.WARN);
assertThat(getClassNode(TestCls.class))
.code()
.doesNotContain("AnonymousClass1.this")
.doesNotContain("class AnonymousClass1")
// .doesNotContain("TestAnonymousClass18$TestCls.runJob(") // TODO: ???
.containsOne(indent() + "doSomething();");
}

@Test
public void testNoInline() {
getArgs().setInlineAnonymousClasses(false);
assertThat(getClassNode(TestCls.class))
.code()
.containsOne("class AnonymousClass1 implements Job {")
.containsOne("class C00001 implements Job {")
.containsOne("AnonymousClass1.this.doSomething();");
}
}

0 comments on commit d2bde0b

Please sign in to comment.