diff options
Diffstat (limited to 'src')
3 files changed, 86 insertions, 22 deletions
diff --git a/src/main/java/org/zwobble/couscous/frontends/java/JavaExpressionReader.java b/src/main/java/org/zwobble/couscous/frontends/java/JavaExpressionReader.java index e5cbf2d..f1af093 100644 --- a/src/main/java/org/zwobble/couscous/frontends/java/JavaExpressionReader.java +++ b/src/main/java/org/zwobble/couscous/frontends/java/JavaExpressionReader.java @@ -6,6 +6,7 @@ import org.zwobble.couscous.values.BooleanValue; import org.zwobble.couscous.values.IntegerValue; import org.zwobble.couscous.values.ObjectValues; +import java.util.Collections; import java.util.List; import java.util.stream.Collectors; import java.util.stream.IntStream; @@ -100,6 +101,9 @@ public class JavaExpressionReader { case ASTNode.CLASS_INSTANCE_CREATION: return readClassInstanceCreation((ClassInstanceCreation)expression); + case ASTNode.LAMBDA_EXPRESSION: + return readLambdaExpression((LambdaExpression)expression); + case ASTNode.INFIX_EXPRESSION: return readInfixExpression((InfixExpression)expression); @@ -198,6 +202,11 @@ public class JavaExpressionReader { } } + private ExpressionNode readLambdaExpression(LambdaExpression expression) { + TypeName anonymousClassName = javaReader.readLambda(expression); + return constructorCall(anonymousClassName, Collections.emptyList()); + } + private List<ExpressionNode> readArguments(IMethodBinding method, List<Expression> javaArguments) { return IntStream.range(0, javaArguments.size()) .mapToObj(index -> readExpression( 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 2395f38..10cc6ec 100644 --- a/src/main/java/org/zwobble/couscous/frontends/java/JavaReader.java +++ b/src/main/java/org/zwobble/couscous/frontends/java/JavaReader.java @@ -2,16 +2,14 @@ package org.zwobble.couscous.frontends.java; import com.google.common.collect.ImmutableList; import org.eclipse.jdt.core.dom.*; -import org.zwobble.couscous.ast.ClassNode; -import org.zwobble.couscous.ast.ClassNodeBuilder; -import org.zwobble.couscous.ast.StatementNode; -import org.zwobble.couscous.ast.TypeName; +import org.zwobble.couscous.ast.*; import java.io.IOException; import java.nio.file.Path; import java.util.List; import java.util.Optional; +import static org.zwobble.couscous.ast.ReturnNode.returns; import static org.zwobble.couscous.frontends.java.JavaTypes.typeOf; import static org.zwobble.couscous.util.ExtraLists.cons; import static org.zwobble.couscous.util.ExtraLists.ofType; @@ -36,6 +34,33 @@ public class JavaReader { return readTypeDeclarationBody(name, type.bodyDeclarations()); } + TypeName readLambda(LambdaExpression expression) { + IMethodBinding methodBinding = expression.resolveMethodBinding(); + IMethodBinding functionalInterfaceMethod = expression.resolveTypeBinding().getFunctionalInterfaceMethod(); + TypeName returnType = typeOf(functionalInterfaceMethod.getReturnType()); + + ClassNodeBuilder classBuilder = new ClassNodeBuilder(generateClassName(expression)); + classBuilder.method(functionalInterfaceMethod.getName(), method -> { + ASTNode body = expression.getBody(); + if ((body instanceof Expression)) { + method.statement(returns(expressionReader().readExpression( + returnType, + (Expression)body))); + } else { + throw new UnsupportedOperationException(); + } + return method; + }); + + ClassNode classNode = classBuilder.build(); + classes.add(classNode); + return classNode.getName(); + } + + private String generateClassName(LambdaExpression expression) { + return generateClassName(expression.resolveMethodBinding().getDeclaringClass()); + } + TypeName readAnonymousClass(AnonymousClassDeclaration declaration) { String name = generateClassName(declaration); ClassNode classNode = readTypeDeclarationBody(name, declaration.bodyDeclarations()); @@ -45,6 +70,10 @@ public class JavaReader { private String generateClassName(AnonymousClassDeclaration declaration) { ITypeBinding type = declaration.resolveBinding(); + return generateClassName(type); + } + + private String generateClassName(ITypeBinding type) { while (type.isAnonymous()) { type = type.getDeclaringClass(); } @@ -63,20 +92,20 @@ public class JavaReader { readField(field, classBuilder); } } - + private void readField(FieldDeclaration field, ClassNodeBuilder classBuilder) { for (Object fragment : field.fragments()) { String name = ((VariableDeclarationFragment)fragment).getName().getIdentifier(); classBuilder.field(name, typeOf(field.getType())); } } - + private void readMethods(List<MethodDeclaration> methods, ClassNodeBuilder classBuilder) { for (MethodDeclaration method : methods) { readMethod(classBuilder, method); } } - + private void readMethod(ClassNodeBuilder classBuilder, MethodDeclaration method) { if (method.isConstructor()) { classBuilder.constructor(builder -> buildMethod(method, builder)); @@ -99,7 +128,7 @@ public class JavaReader { Optional<TypeName> returnType = method.getReturnType2() == null ? Optional.empty() : Optional.of(typeOf(method.getReturnType2())); - JavaStatementReader statementReader = new JavaStatementReader(new JavaExpressionReader(this), returnType); + JavaStatementReader statementReader = new JavaStatementReader(expressionReader(), returnType); for (Object statement : method.getBody().statements()) { for (StatementNode intermediateStatement : statementReader.readStatement((Statement)statement)) { builder.statement(intermediateStatement); @@ -112,4 +141,8 @@ public class JavaReader { TypeDeclaration type = (TypeDeclaration)ast.types().get(0); return ast.getPackage().getName().getFullyQualifiedName() + "." + type.getName().getFullyQualifiedName(); } + + private JavaExpressionReader expressionReader() { + return new JavaExpressionReader(this); + } }
\ No newline at end of file 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 e09f2af..5fd26c0 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 @@ -153,6 +153,19 @@ public class JavaReaderTests { constructorCall(TypeName.of("java.lang.String"), asList(literal("_"))), readObjectExpression("new String(\"_\")")); } + + @Test + public void lambdaIsReadAsAnonymousClassCreation() { + assertEquals( + readClasses(generateMethodSource("void", + "java.util.function.Supplier<Integer> supplier = new java.util.function.Supplier<Integer>() {\n" + + " public Integer get() {\n" + + " return 42;\n" + + " }\n" + + "};")), + readClasses(generateMethodSource("void", + "java.util.function.Supplier<Integer> supplier = () -> 42;"))); + } @Test public void argumentIsBoxedIfNecessary() { @@ -604,21 +617,19 @@ public class JavaReaderTests { } private List<StatementNode> readStatements(String returnType, String statementsSource) { - String javaClass = - "public static " + returnType + " main() {" + - statementsSource + - "}"; - + String javaClass = generateMethodSource(returnType, statementsSource); ClassNode classNode = readClass(javaClass); return classNode.getMethods().get(0).getBody(); } private ClassNode readClass(String classBody) { - String javaClass = - "package com.example;" + - "public class Example {" + - classBody + - "}"; + List<ClassNode> classes = readClasses(classBody); + assertThat(classes, hasSize(1)); + return classes.get(0); + } + + private List<ClassNode> readClasses(String classBody) { + String javaClass = generateClassSource(classBody); try { Path directoryPath = Files.createTempDirectory(null); @@ -626,10 +637,8 @@ public class JavaReaderTests { try { Files.createDirectories(directoryPath.resolve("com/example")); Files.write(sourcePath, asList(javaClass)); - - List<ClassNode> classes = JavaReader.readClassFromFile(directoryPath, sourcePath); - assertThat(classes, hasSize(1)); - return classes.get(0); + + return JavaReader.readClassFromFile(directoryPath, sourcePath); } finally { deleteRecursively(directoryPath.toFile()); } @@ -637,4 +646,17 @@ public class JavaReaderTests { throw new RuntimeException(exception); } } + + private String generateMethodSource(String returnType, String statementsSource) { + return "public static " + returnType + " main() {" + + statementsSource + + "}"; + } + + private String generateClassSource(String classBody) { + return "package com.example;" + + "public class Example {" + + classBody + + "}"; + } } |
