diff options
3 files changed, 48 insertions, 12 deletions
diff --git a/src/main/java/org/zwobble/couscous/frontends/java/JavaExpressionMethodReferenceReader.java b/src/main/java/org/zwobble/couscous/frontends/java/JavaExpressionMethodReferenceReader.java index 8780082..6c49d4e 100644 --- a/src/main/java/org/zwobble/couscous/frontends/java/JavaExpressionMethodReferenceReader.java +++ b/src/main/java/org/zwobble/couscous/frontends/java/JavaExpressionMethodReferenceReader.java @@ -4,12 +4,13 @@ import com.google.common.collect.ImmutableList; import org.eclipse.jdt.core.dom.ExpressionMethodReference; import org.eclipse.jdt.core.dom.IMethodBinding; import org.eclipse.jdt.core.dom.ITypeBinding; -import org.zwobble.couscous.ast.FormalArgumentNode; -import org.zwobble.couscous.ast.VariableReferenceNode; +import org.eclipse.jdt.core.dom.Modifier; +import org.zwobble.couscous.ast.*; import org.zwobble.couscous.ast.sugar.Lambda; import java.util.List; +import static org.zwobble.couscous.ast.MethodCallNode.methodCall; import static org.zwobble.couscous.ast.ReturnNode.returns; import static org.zwobble.couscous.ast.StaticMethodCallNode.staticMethodCall; import static org.zwobble.couscous.ast.sugar.Lambda.lambda; @@ -17,7 +18,13 @@ import static org.zwobble.couscous.frontends.java.JavaTypes.typeOf; import static org.zwobble.couscous.util.ExtraLists.eagerMap; public class JavaExpressionMethodReferenceReader { - public static Lambda expressionMethodReferenceToLambda(Scope scope, ExpressionMethodReference expression) { + private final JavaReader javaReader; + + public JavaExpressionMethodReferenceReader(JavaReader javaReader) { + this.javaReader = javaReader; + } + + public Lambda toLambda(Scope scope, ExpressionMethodReference expression) { IMethodBinding functionalInterfaceMethod = expression.resolveTypeBinding().getFunctionalInterfaceMethod(); List<FormalArgumentNode> formalArguments = formalArguments(scope, functionalInterfaceMethod); @@ -25,14 +32,10 @@ public class JavaExpressionMethodReferenceReader { formalArguments, ImmutableList.of(returns(JavaExpressionReader.handleBoxing( typeOf(functionalInterfaceMethod.getReturnType()), - staticMethodCall( - typeOf(expression.resolveMethodBinding().getDeclaringClass()), - expression.getName().getIdentifier(), - eagerMap(formalArguments, VariableReferenceNode::reference), - typeOf(expression.resolveMethodBinding().getReturnType())))))); + generateValue(scope, expression, formalArguments))))); } - private static List<FormalArgumentNode> formalArguments(Scope scope, IMethodBinding functionalInterfaceMethod) { + private List<FormalArgumentNode> formalArguments(Scope scope, IMethodBinding functionalInterfaceMethod) { ImmutableList.Builder<FormalArgumentNode> arguments = ImmutableList.builder(); ITypeBinding[] parameterTypes = functionalInterfaceMethod.getParameterTypes(); @@ -43,4 +46,25 @@ public class JavaExpressionMethodReferenceReader { return arguments.build(); } + + private ExpressionNode generateValue(Scope scope, ExpressionMethodReference expression, List<FormalArgumentNode> formalArguments) { + IMethodBinding methodBinding = expression.resolveMethodBinding(); + String methodName = expression.getName().getIdentifier(); + List<ExpressionNode> arguments = eagerMap(formalArguments, VariableReferenceNode::reference); + TypeName type = typeOf(methodBinding.getReturnType()); + + if (Modifier.isStatic(methodBinding.getModifiers())) { + return staticMethodCall( + typeOf(methodBinding.getDeclaringClass()), + methodName, + arguments, + type); + } else { + return methodCall( + javaReader.readExpressionWithoutBoxing(scope, expression.getExpression()), + methodName, + arguments, + type); + } + } } diff --git a/src/main/java/org/zwobble/couscous/frontends/java/JavaReader.java b/src/main/java/org/zwobble/couscous/frontends/java/JavaReader.java index 86ad12d..1c53a44 100644 --- a/src/main/java/org/zwobble/couscous/frontends/java/JavaReader.java +++ b/src/main/java/org/zwobble/couscous/frontends/java/JavaReader.java @@ -31,7 +31,6 @@ import static org.zwobble.couscous.ast.FormalArgumentNode.formalArg; import static org.zwobble.couscous.ast.ThisReferenceNode.thisReference; import static org.zwobble.couscous.ast.VariableReferenceNode.reference; import static org.zwobble.couscous.frontends.java.FreeVariables.findFreeVariables; -import static org.zwobble.couscous.frontends.java.JavaExpressionMethodReferenceReader.expressionMethodReferenceToLambda; import static org.zwobble.couscous.frontends.java.JavaTypes.*; import static org.zwobble.couscous.util.Casts.tryCast; import static org.zwobble.couscous.util.ExtraLists.*; @@ -75,7 +74,7 @@ public class JavaReader { scope, name, expression.resolveTypeBinding().getFunctionalInterfaceMethod(), - expressionMethodReferenceToLambda(scope, expression)); + new JavaExpressionMethodReferenceReader(this).toLambda(scope, expression)); } GeneratedClosure readLambda(Scope outerScope, LambdaExpression expression) { @@ -320,6 +319,10 @@ public class JavaReader { return expressionReader(scope).readExpression(targetType, body); } + ExpressionNode readExpressionWithoutBoxing(Scope scope, Expression body) { + return expressionReader(scope).readExpressionWithoutBoxing(body); + } + private TypeName generateClassName(CompilationUnit ast) { TypeDeclaration type = (TypeDeclaration)ast.types().get(0); String packageName = ast.getPackage().getName().getFullyQualifiedName(); diff --git a/src/test/java/org/zwobble/couscous/tests/frontends/java/JavaReaderTests.java b/src/test/java/org/zwobble/couscous/tests/frontends/java/JavaReaderTests.java index 15404a4..aa304f6 100644 --- a/src/test/java/org/zwobble/couscous/tests/frontends/java/JavaReaderTests.java +++ b/src/test/java/org/zwobble/couscous/tests/frontends/java/JavaReaderTests.java @@ -187,13 +187,22 @@ public class JavaReaderTests { } @Test - public void expressionMethodReferenceIsReadAsLambda() { + public void expressionMethodReferenceWithStaticReceiverIsReadAsLambda() { assertEquals( readClasses(generateMethodSource("void", "java.util.function.Function<String, Integer> function = arg0 -> Integer.parseInt(arg0);")), readClasses(generateMethodSource("void", "java.util.function.Function<String, Integer> function = Integer::parseInt;"))); } + + @Test + public void expressionMethodReferenceWithInstanceReceiverIsReadAsLambda() { + assertEquals( + readClasses(generateMethodSource("void", + "Integer x = 0; java.util.function.Supplier<String> function = () -> x.toString();")), + readClasses(generateMethodSource("void", + "Integer x = 0; java.util.function.Supplier<String> function = x::toString;"))); + } @Test public void argumentIsBoxedIfNecessary() { |
