diff options
| author | Michael Williamson <mike@zwobble.org> | 2016-04-04 22:42:15 +0100 |
|---|---|---|
| committer | Michael Williamson <mike@zwobble.org> | 2016-04-05 22:28:43 +0100 |
| commit | 63fc003231e92e8f5ea2af29a04ba5507c212325 (patch) | |
| tree | aa75d120c99570340402f06edffb9acc357f8394 | |
| parent | 449c10917348eee52c2d769eb5f6fb7f8ec836b9 (diff) | |
Partial support for reading type parameters for methods
6 files changed, 67 insertions, 23 deletions
diff --git a/src/main/java/org/zwobble/couscous/ast/MethodNode.java b/src/main/java/org/zwobble/couscous/ast/MethodNode.java index 8863619..1e682fb 100644 --- a/src/main/java/org/zwobble/couscous/ast/MethodNode.java +++ b/src/main/java/org/zwobble/couscous/ast/MethodNode.java @@ -11,6 +11,7 @@ import java.util.Optional; import java.util.function.Function; import static org.zwobble.couscous.util.ExtraLists.eagerMap; +import static org.zwobble.couscous.util.ExtraLists.list; public class MethodNode implements Node { public static Builder staticMethod(String name) { @@ -83,6 +84,7 @@ public class MethodNode implements Node { annotations.build(), isStatic, name, + list(), arguments.build(), returnType, isAbstract ? Optional.empty() : Optional.of(body.build()), @@ -94,17 +96,19 @@ public class MethodNode implements Node { List<AnnotationNode> annotations, boolean isStatic, String name, + List<FormalTypeParameterNode> typeParameters, List<FormalArgumentNode> arguments, Type returnType, Optional<List<StatementNode>> body, List<MethodSignature> overrides) { - return new MethodNode(annotations, isStatic, name, arguments, returnType, body, overrides); + return new MethodNode(annotations, isStatic, name, typeParameters, arguments, returnType, body, overrides); } private final List<AnnotationNode> annotations; private final boolean isStatic; private final String name; + private final List<FormalTypeParameterNode> typeParameters; private final List<FormalArgumentNode> arguments; private final Type returnType; private final Optional<List<StatementNode>> body; @@ -114,6 +118,7 @@ public class MethodNode implements Node { List<AnnotationNode> annotations, boolean isStatic, String name, + List<FormalTypeParameterNode> typeParameters, List<FormalArgumentNode> arguments, Type returnType, Optional<List<StatementNode>> body, @@ -122,6 +127,7 @@ public class MethodNode implements Node { this.annotations = annotations; this.isStatic = isStatic; this.name = name; + this.typeParameters = typeParameters; this.arguments = arguments; this.returnType = returnType; this.body = body; @@ -139,7 +145,11 @@ public class MethodNode implements Node { public String getName() { return name; } - + + public List<FormalTypeParameterNode> getTypeParameters() { + return typeParameters; + } + public List<FormalArgumentNode> getArguments() { return arguments; } @@ -168,7 +178,7 @@ public class MethodNode implements Node { } public MethodNode mapBody(Function<List<StatementNode>, List<StatementNode>> function) { - return new MethodNode(annotations, isStatic, name, arguments, returnType, body.map(function), overrides); + return new MethodNode(annotations, isStatic, name, typeParameters, arguments, returnType, body.map(function), overrides); } @Override @@ -181,6 +191,7 @@ public class MethodNode implements Node { transformer.transformAnnotations(annotations), isStatic, transformer.transformMethodName(signature()), + transformer.transformFormalTypeParameters(typeParameters), transformer.transformFormalArguments(arguments), transformer.transform(returnType), body.map(transformer::transformStatements), @@ -188,6 +199,20 @@ public class MethodNode implements Node { } @Override + public String toString() { + return "MethodNode(" + + "annotations=" + annotations + + ", isStatic=" + isStatic + + ", name=" + name + + ", typeParameters=" + typeParameters + + ", arguments=" + arguments + + ", returnType=" + returnType + + ", body=" + body + + ", overrides=" + overrides + + ')'; + } + + @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; @@ -197,6 +222,7 @@ public class MethodNode implements Node { if (isStatic != that.isStatic) return false; if (!annotations.equals(that.annotations)) return false; if (!name.equals(that.name)) return false; + if (!typeParameters.equals(that.typeParameters)) return false; if (!arguments.equals(that.arguments)) return false; if (!returnType.equals(that.returnType)) return false; if (!body.equals(that.body)) return false; @@ -209,24 +235,11 @@ public class MethodNode implements Node { int result = annotations.hashCode(); result = 31 * result + (isStatic ? 1 : 0); result = 31 * result + name.hashCode(); + result = 31 * result + typeParameters.hashCode(); result = 31 * result + arguments.hashCode(); result = 31 * result + returnType.hashCode(); result = 31 * result + body.hashCode(); result = 31 * result + overrides.hashCode(); return result; } - - @Override - public String toString() { - return "MethodNode(" + - "annotations=" + annotations + - ", isStatic=" + isStatic + - ", name=" + name + - ", arguments=" + arguments + - ", returnType=" + returnType + - ", body=" + body + - ", overrides=" + overrides + - ')'; - } - } diff --git a/src/main/java/org/zwobble/couscous/backends/python/PythonCodeGenerator.java b/src/main/java/org/zwobble/couscous/backends/python/PythonCodeGenerator.java index 73e6ced..4036a85 100644 --- a/src/main/java/org/zwobble/couscous/backends/python/PythonCodeGenerator.java +++ b/src/main/java/org/zwobble/couscous/backends/python/PythonCodeGenerator.java @@ -208,6 +208,8 @@ public class PythonCodeGenerator { methodNode.getAnnotations(), methodNode.isStatic(), methodNode.getName(), + // TODO: should get type parameters from signature + list(), arguments, override.getReturnType(), Optional.of(list(body)), 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 d4366c2..063ffc6 100644 --- a/src/main/java/org/zwobble/couscous/frontends/java/JavaReader.java +++ b/src/main/java/org/zwobble/couscous/frontends/java/JavaReader.java @@ -117,8 +117,12 @@ public class JavaReader { } private List<FormalTypeParameterNode> readTypeParameters(TypeDeclaration typeDeclaration) { + return readTypeParameters(typeDeclaration.resolveBinding().getTypeParameters()); + } + + private List<FormalTypeParameterNode> readTypeParameters(ITypeBinding[] typeParameters) { return eagerMap( - asList(typeDeclaration.resolveBinding().getTypeParameters()), + asList(typeParameters), parameter -> formalTypeParameter(parameter.getName())); } @@ -156,6 +160,8 @@ public class JavaReader { emptyList(), false, functionalInterfaceMethod.getName(), + // TODO: should get formal type parameters from the lambda + list(), lambda.getFormalArguments(), typeOf(functionalInterfaceMethod.getReturnType()), Optional.of(lambda.getBody()), @@ -414,6 +420,7 @@ public class JavaReader { annotations, isStatic, methodName, + readTypeParameters(method.resolveBinding().getTypeParameters()), formalArguments, returnType.get(), body, diff --git a/src/main/java/org/zwobble/couscous/frontends/java/JavaTypes.java b/src/main/java/org/zwobble/couscous/frontends/java/JavaTypes.java index d63ec89..3b7a472 100644 --- a/src/main/java/org/zwobble/couscous/frontends/java/JavaTypes.java +++ b/src/main/java/org/zwobble/couscous/frontends/java/JavaTypes.java @@ -41,8 +41,11 @@ public class JavaTypes { return Types.array(typeOf(typeBinding.getElementType())); } ITypeBinding outerClass = typeBinding.getDeclaringClass(); - // TODO: handle type variables for methods - if (typeBinding.isTypeVariable() && outerClass != null) { + if (typeBinding.isTypeVariable()) { + if (outerClass == null) { + // TODO: handle type variables for methods properly + outerClass = typeBinding.getDeclaringMethod().getDeclaringClass(); + } return new TypeParameter(erasure(typeOf(outerClass)), typeBinding.getName()); } ScalarType rawType = outerClass == null 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 5bcb044..4a05385 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 @@ -29,7 +29,9 @@ import static org.zwobble.couscous.ast.TypeCoercionNode.typeCoercion; import static org.zwobble.couscous.ast.VariableReferenceNode.reference; import static org.zwobble.couscous.ast.WhileNode.whileLoop; import static org.zwobble.couscous.tests.frontends.java.JavaReading.*; -import static org.zwobble.couscous.tests.frontends.java.NodeMatchers.isArgument; +import static org.zwobble.couscous.tests.frontends.java.NodeMatchers.isFormalArgument; +import static org.zwobble.couscous.tests.frontends.java.NodeMatchers.isFormalTypeParameter; +import static org.zwobble.couscous.types.TypeParameter.typeParameter; import static org.zwobble.couscous.util.ExtraLists.list; import static org.zwobble.couscous.util.ExtraSets.set; @@ -75,11 +77,24 @@ public class JavaReaderTests { "}"); MethodNode method = classNode.getMethods().get(0); - assertThat(method.getArguments(), contains(isArgument("value", ScalarType.of("int")))); + assertThat(method.getArguments(), contains(isFormalArgument("value", ScalarType.of("int")))); ReturnNode returnNode = (ReturnNode)method.getBody().get().get(0); assertEquals(reference(method.getArguments().get(0)), returnNode.getValue()); } + + @Test + public void canReadTypeParametersForMethod() { + ClassNode classNode = readClass( + "public <T> T identity(T value) {" + + " return value;" + + "}"); + + MethodNode method = classNode.getMethods().get(0); + assertThat(method.getTypeParameters(), contains(isFormalTypeParameter("T"))); + // TODO: typeParameter should be declared on method, not class + assertThat(method.getArguments(), contains(isFormalArgument("value", typeParameter(classNode.getName(), "T")))); + } @Test public void canReadExpressionStatements() { diff --git a/src/test/java/org/zwobble/couscous/tests/frontends/java/NodeMatchers.java b/src/test/java/org/zwobble/couscous/tests/frontends/java/NodeMatchers.java index efd4eb4..104cf8b 100644 --- a/src/test/java/org/zwobble/couscous/tests/frontends/java/NodeMatchers.java +++ b/src/test/java/org/zwobble/couscous/tests/frontends/java/NodeMatchers.java @@ -14,7 +14,11 @@ public class NodeMatchers { return hasFeature("initial value", node -> node.getInitialValue(), matcher); } - public static Matcher<FormalArgumentNode> isArgument(String name, Type type) { + public static Matcher<FormalTypeParameterNode> isFormalTypeParameter(String name) { + return hasFeature("name", node -> node.getName(), equalTo(name)); + } + + public static Matcher<FormalArgumentNode> isFormalArgument(String name, Type type) { return allOf( hasFeature("name", node -> node.getName(), equalTo(name)), hasFeature("type", node -> node.getType(), equalTo(type))); |
