diff --git a/jadx-core/src/main/java/jadx/core/codegen/InsnGen.java b/jadx-core/src/main/java/jadx/core/codegen/InsnGen.java index 80c0ecdc7..bee09d490 100644 --- a/jadx-core/src/main/java/jadx/core/codegen/InsnGen.java +++ b/jadx-core/src/main/java/jadx/core/codegen/InsnGen.java @@ -1016,9 +1016,14 @@ public class InsnGen { int startArg = customNode.getHandleType() == MethodHandleType.INVOKE_STATIC ? 0 : 1; // skip 'this' arg int callArg = 0; for (int i = startArg; i < extArgsCount; i++) { - RegisterArg extArg = (RegisterArg) customNode.getArg(i); - RegisterArg callRegArg = callArgs.get(callArg++); - callRegArg.getSVar().setCodeVar(extArg.getSVar().getCodeVar()); + InsnArg arg = customNode.getArg(i); + if (arg.isRegister()) { + RegisterArg extArg = (RegisterArg) arg; + RegisterArg callRegArg = callArgs.get(callArg++); + callRegArg.getSVar().setCodeVar(extArg.getSVar().getCodeVar()); + } else { + throw new JadxRuntimeException("Unexpected argument type in lambda call: " + arg.getClass().getSimpleName()); + } } code.add(" -> {"); code.incIndent(); @@ -1075,27 +1080,23 @@ public class InsnGen { } int argsCount = insn.getArgsCount(); code.add('('); + SkipMethodArgsAttr skipAttr = mthNode == null ? null : mthNode.get(AType.SKIP_MTH_ARGS); boolean firstArg = true; if (k < argsCount) { for (int i = k; i < argsCount; i++) { InsnArg arg = insn.getArg(i); - if (arg.contains(AFlag.SKIP_ARG)) { + if (arg.contains(AFlag.SKIP_ARG) || (skipAttr != null && skipAttr.isSkip(i - startArgNum))) { continue; } - int argOrigPos = i - startArgNum; - if (SkipMethodArgsAttr.isSkip(mthNode, argOrigPos)) { - continue; - } - if (!firstArg) { - code.add(", "); - } else { + if (firstArg) { firstArg = false; + } else { + code.add(", "); } if (i == argsCount - 1 && processVarArg(code, insn, arg)) { continue; } addArg(code, arg, false); - firstArg = false; } } code.add(')'); diff --git a/jadx-core/src/main/java/jadx/core/dex/visitors/ConstInlineVisitor.java b/jadx-core/src/main/java/jadx/core/dex/visitors/ConstInlineVisitor.java index 564584d47..9e0a8ffef 100644 --- a/jadx-core/src/main/java/jadx/core/dex/visitors/ConstInlineVisitor.java +++ b/jadx-core/src/main/java/jadx/core/dex/visitors/ConstInlineVisitor.java @@ -16,6 +16,7 @@ import jadx.core.dex.instructions.args.LiteralArg; import jadx.core.dex.instructions.args.PrimitiveType; import jadx.core.dex.instructions.args.RegisterArg; import jadx.core.dex.instructions.args.SSAVar; +import jadx.core.dex.instructions.mods.ConstructorInsn; import jadx.core.dex.nodes.BlockNode; import jadx.core.dex.nodes.FieldNode; import jadx.core.dex.nodes.InsnNode; @@ -178,7 +179,7 @@ public class ConstInlineVisitor extends AbstractVisitor { List useList = new ArrayList<>(ssaVar.getUseList()); int replaceCount = 0; for (RegisterArg arg : useList) { - if (canInline(arg) && replaceArg(mth, arg, constArg, constInsn)) { + if (canInline(mth, arg) && replaceArg(mth, arg, constArg, constInsn)) { replaceCount++; } } @@ -204,8 +205,8 @@ public class ConstInlineVisitor extends AbstractVisitor { } @SuppressWarnings("RedundantIfStatement") - private static boolean canInline(RegisterArg arg) { - if (arg.contains(AFlag.DONT_INLINE_CONST)) { + private static boolean canInline(MethodNode mth, RegisterArg arg) { + if (arg.contains(AFlag.DONT_INLINE_CONST) || arg.contains(AFlag.DONT_INLINE)) { return false; } InsnNode parentInsn = arg.getParentInsn(); @@ -219,6 +220,14 @@ public class ConstInlineVisitor extends AbstractVisitor { // don't inline vars used in finally block return false; } + if (parentInsn.getType() == InsnType.CONSTRUCTOR) { + // don't inline into anonymous call if it can be inlined later + ConstructorInsn ctrInsn = (ConstructorInsn) parentInsn; + MethodNode ctrMth = mth.root().getMethodUtils().resolveMethod(ctrInsn); + if (ctrMth != null && ctrMth.contains(AFlag.METHOD_CANDIDATE_FOR_INLINE)) { + return false; + } + } return true; } diff --git a/jadx-core/src/test/java/jadx/tests/integration/java8/TestLambdaExtVar2.java b/jadx-core/src/test/java/jadx/tests/integration/java8/TestLambdaExtVar2.java new file mode 100644 index 000000000..85c9be3bf --- /dev/null +++ b/jadx-core/src/test/java/jadx/tests/integration/java8/TestLambdaExtVar2.java @@ -0,0 +1,37 @@ +package jadx.tests.integration.java8; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import jadx.tests.api.IntegrationTest; +import jadx.tests.api.extensions.profiles.TestProfile; +import jadx.tests.api.extensions.profiles.TestWithProfiles; + +import static jadx.tests.api.utils.assertj.JadxAssertions.assertThat; + +public class TestLambdaExtVar2 extends IntegrationTest { + + public static class TestCls { + + public void test(List list) { + String space = " "; + list.removeIf(s -> s.equals(space) || s.contains(space)); + } + + public void check() { + List list = new ArrayList<>(Arrays.asList("a", " ", "b", "r ")); + test(list); + assertThat(list).isEqualTo(Arrays.asList("a", "b")); + } + } + + @TestWithProfiles({ TestProfile.DX_J8, TestProfile.D8_J11, TestProfile.JAVA11 }) + public void test() { + assertThat(getClassNode(TestCls.class)) + .code() + .doesNotContain("lambda$") + .containsOne("String space = \" \";") + .containsOne("s.equals(space) || s.contains(space)"); + } +}