<div dir="ltr">Hello!<div><br></div><div>I'm continuing working on my toy decompiler-interpreter-asserts-library and trying to restore a method reference from the code model. I've noticed that there's a LambdaOp.methodReference() method. However, it works for only one method reference case: instance method without qualifier expression. In other cases, it returns null. More specifically:</div><div>String::isEmpty -- works</div><div>Integer::valueOf -- doesn't work</div><div>"xyz"::equals -- doesn't work</div><div>String::new -- doesn't work</div><div><br></div><div>Probably it's not implemented yet and still in the queue, I just wanted to ensure that current behavior is not final.</div><div><br></div><div>Concentrating on a single working case (String::isEmpty), I need to construct a functional lambda. We don't need to capture anything here, which simplifies things a bit, but still the construction takes some effort. My best attempt is the following (error handling removed for brevity):</div><div><br></div><div>CoreOp.InvokeOp invokeOp = lambdaOp.methodReference().get();<br>MethodHandle handle = invokeOp.invokeDescriptor().resolveToHandle(lookup);<br>Class<?> fnClass = toClass(lambdaOp.functionalInterface());</div><div>// It looks like finding SAM is necessary. Is there an easier way of getting it?<br></div><div>Method sam = Stream.of(fnClass.getMethods())</div><div>       .filter(m -> Modifier.isAbstract(m.getModifiers())).findFirst().get();<br>MethodType samMethodType = MethodType.methodType(sam.getReturnType(), sam.getParameterTypes());<br>MethodType dynamicType = toMethodType(lambdaOp.invokableType());<br>CallSite callSite = LambdaMetafactory.metafactory(lookup, sam.getName(), MethodType.methodType(fnClass),<br>            samMethodType, handle, dynamicType);<br>Object lambda = callSite.dynamicInvoker().invoke();</div><div>... use lambda ...<br></div><div><br></div><div>The toMethodType() is the following helper:</div><div><br></div><div>private MethodType toMethodType(FunctionType functionType) {<br>  Class<?> rType = toClass(functionType.returnType());<br>  Class<?>[] pTypes = functionType.parameterTypes().stream().map(this::toClass).toArray(Class[]::new);<br>  return MethodType.methodType(rType, pTypes);<br>}<br><br></div><div>Which in turn uses another helper toClass to convert TypeElement to Class<?></div><div><br></div><div>So, quite a lot of code. The first thing which could be improved is providing toMethodType(lookup) instance method directly inside FunctionType. It could be nice to have a convenient bridge between TypeElement world and MethodType world.</div><div><br></div><div>But probably it would be reasonable to resolve a LambdaOp directly to CallSite, encapsulating all this stuff I write? In my application, I don't need to do something fancy with nested lambdas, I just want to run them normally. Not sure, but probably this could be reasonable in other applications as well. Just something to think about.</div><div><br></div><div>With best regards,</div><div>Tagir Valeev</div></div>