fix: lambda decoding and code generation (#2139)
This commit is contained in:
@@ -936,7 +936,7 @@ public class InsnGen {
|
||||
makeInlinedLambdaMethod(code, customNode, callMth);
|
||||
}
|
||||
|
||||
private void makeRefLambda(ICodeWriter code, InvokeCustomNode customNode) {
|
||||
private void makeRefLambda(ICodeWriter code, InvokeCustomNode customNode) throws CodegenException {
|
||||
InsnNode callInsn = customNode.getCallInsn();
|
||||
if (callInsn instanceof ConstructorInsn) {
|
||||
MethodInfo callMth = ((ConstructorInsn) callInsn).getCallMth();
|
||||
@@ -950,7 +950,7 @@ public class InsnGen {
|
||||
if (customNode.getHandleType() == MethodHandleType.INVOKE_STATIC) {
|
||||
useClass(code, callMth.getDeclClass());
|
||||
} else {
|
||||
code.add("this");
|
||||
addArg(code, customNode.getArg(0));
|
||||
}
|
||||
code.add("::").add(callMth.getAlias());
|
||||
}
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
package jadx.tests.integration.java8;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import jadx.tests.api.RaungTest;
|
||||
|
||||
import static jadx.tests.api.utils.assertj.JadxAssertions.assertThat;
|
||||
|
||||
@SuppressWarnings("DataFlowIssue")
|
||||
public class TestLambdaInstance3 extends RaungTest {
|
||||
|
||||
public interface TestCls<R> extends Supplier<R> {
|
||||
default TestCls<R> test() {
|
||||
return (TestCls<R> & Memoized) Lazy.of(this)::get;
|
||||
}
|
||||
}
|
||||
|
||||
public static final class Lazy<T> implements Supplier<T> {
|
||||
public static <T> Lazy<T> of(Supplier<? extends T> supplier) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T get() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
interface Memoized {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
// some java versions failed to compile usage of interface with '$' in name
|
||||
addClsRename("jadx.tests.integration.java8.TestLambdaInstance3$TestCls", "java8.TestCls");
|
||||
assertThat(getClassNode(TestCls.class))
|
||||
.code()
|
||||
.doesNotContain("this::get")
|
||||
.containsOne("return (TestCls) of::get;");
|
||||
// TODO: type inference set type for 'of' to Memoized and cast incorrectly removed
|
||||
// .containsOne("Memoized)");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRaung() {
|
||||
disableCompilation();
|
||||
assertThat(getClassNodeFromRaung())
|
||||
.code()
|
||||
.doesNotContain("this::get")
|
||||
.containsOne(" of::get");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
.version 52 # Java 8
|
||||
.class public interface abstract java8/TestLambdaInstance3
|
||||
.implements java/io/Serializable
|
||||
.implements java/util/function/Supplier
|
||||
.signature <R:Ljava/lang/Object;>Ljava/lang/Object;Ljava/io/Serializable;Ljava/util/function/Supplier<TR;>;
|
||||
.source "Function0.java"
|
||||
.annotation runtime Ljava/lang/FunctionalInterface;
|
||||
.end annotation
|
||||
|
||||
|
||||
.method public memoized()Ljava8/TestLambdaInstance3;
|
||||
.signature ()Ljava8/TestLambdaInstance3<TR;>;
|
||||
.max stack 2
|
||||
.max locals 1
|
||||
|
||||
.local 0 "this" Ljava8/TestLambdaInstance3; Ljava8/TestLambdaInstance3<TR;>;
|
||||
.line 197
|
||||
aload 0
|
||||
invokeinterface java8/TestLambdaInstance3 isMemoized ()Z
|
||||
ifeq :L1
|
||||
.line 198
|
||||
aload 0
|
||||
areturn
|
||||
:L1
|
||||
.line 200
|
||||
.stack same
|
||||
aload 0
|
||||
invokestatic test/Lazy of (Ljava/util/function/Supplier;)Ltest/Lazy;
|
||||
dup
|
||||
invokevirtual java/lang/Object getClass ()Ljava/lang/Class;
|
||||
pop
|
||||
invokedynamic apply (Ltest/Lazy;)Ljava8/TestLambdaInstance3;
|
||||
.handle invoke-static java/lang/invoke/LambdaMetafactory altMetafactory (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;
|
||||
.arg 0 .methodtype ()Ljava/lang/Object;
|
||||
.arg 1 .handle invoke-virtual test/Lazy get ()Ljava/lang/Object;
|
||||
.arg 2 .methodtype ()Ljava/lang/Object;
|
||||
.arg 3 7
|
||||
.arg 4 1
|
||||
.arg 5 Ltest/Memoized;
|
||||
.arg 6 0
|
||||
.end invokedynamic
|
||||
checkcast test/Memoized
|
||||
checkcast java8/TestLambdaInstance3
|
||||
areturn
|
||||
.end method
|
||||
+2
@@ -221,6 +221,8 @@ public class ConstPoolReader {
|
||||
return new EncodedValue(EncodedType.ENCODED_LONG, data.readS8());
|
||||
case DOUBLE:
|
||||
return new EncodedValue(EncodedType.ENCODED_DOUBLE, Double.longBitsToDouble(data.readU8()));
|
||||
case CLASS:
|
||||
return new EncodedValue(EncodedType.ENCODED_TYPE, getClass(idx));
|
||||
case METHOD_TYPE:
|
||||
return new EncodedValue(EncodedType.ENCODED_METHOD_TYPE, DescriptorParser.parseToMethodProto(getUtf8(readU2())));
|
||||
case METHOD_HANDLE:
|
||||
|
||||
Reference in New Issue
Block a user