diff options
| author | Michael Williamson <mike@zwobble.org> | 2016-04-09 14:59:32 +0100 |
|---|---|---|
| committer | Michael Williamson <mike@zwobble.org> | 2016-04-09 14:59:32 +0100 |
| commit | 2bc236438ce5d5120c9c34f213b4b49b475dcee2 (patch) | |
| tree | be5008e70cf11ebece0c07165c86c034ddef3920 /src/main/java/org/zwobble/couscous/frontends | |
| parent | 0a550c3bb4e624d76b3876e92a2bd0e235301fba (diff) | |
Read generic signature for method calls
Diffstat (limited to 'src/main/java/org/zwobble/couscous/frontends')
| -rw-r--r-- | src/main/java/org/zwobble/couscous/frontends/java/JavaExpressionReader.java | 12 | ||||
| -rw-r--r-- | src/main/java/org/zwobble/couscous/frontends/java/JavaMethods.java | 54 |
2 files changed, 48 insertions, 18 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 4c27a75..0d19cd1 100644 --- a/src/main/java/org/zwobble/couscous/frontends/java/JavaExpressionReader.java +++ b/src/main/java/org/zwobble/couscous/frontends/java/JavaExpressionReader.java @@ -18,7 +18,6 @@ import static org.zwobble.couscous.ast.ConstructorCallNode.constructorCall; import static org.zwobble.couscous.ast.InstanceReceiver.instanceReceiver; import static org.zwobble.couscous.ast.LiteralNode.literal; import static org.zwobble.couscous.ast.MethodCallNode.methodCall; -import static org.zwobble.couscous.ast.MethodCallNode.staticMethodCall; import static org.zwobble.couscous.ast.OperationNode.operation; import static org.zwobble.couscous.ast.Operations.not; import static org.zwobble.couscous.ast.StaticReceiver.staticReceiver; @@ -210,24 +209,27 @@ public class JavaExpressionReader { List<ExpressionNode> arguments = readArguments( expression.resolveMethodBinding(), expression.arguments()); - MethodSignature signature = JavaMethods.signature(expression.resolveMethodBinding()); + Type returnType = typeOf(expression); + MethodSignature signature = JavaMethods.signature(expression.resolveMethodBinding().getMethodDeclaration()); IMethodBinding methodBinding = expression.resolveMethodBinding(); Type receiverType = typeOf(methodBinding.getDeclaringClass()); if ((Modifier.isStatic(methodBinding.getModifiers()))) { - return staticMethodCall( - erasure(receiverType), + return methodCall( + staticReceiver(erasure(receiverType)), methodName, arguments, + returnType, signature); } else { ExpressionNode receiver = expression.getExpression() == null ? thisReference(receiverType) : readExpressionWithoutBoxing(expression.getExpression()); return methodCall( - receiver, + instanceReceiver(receiver), methodName, arguments, + returnType, signature); } } diff --git a/src/main/java/org/zwobble/couscous/frontends/java/JavaMethods.java b/src/main/java/org/zwobble/couscous/frontends/java/JavaMethods.java index b52110f..014e4ae 100644 --- a/src/main/java/org/zwobble/couscous/frontends/java/JavaMethods.java +++ b/src/main/java/org/zwobble/couscous/frontends/java/JavaMethods.java @@ -4,12 +4,16 @@ import com.google.common.collect.Iterables; import org.eclipse.jdt.core.dom.IMethodBinding; import org.eclipse.jdt.core.dom.ITypeBinding; import org.zwobble.couscous.ast.MethodSignature; +import org.zwobble.couscous.ast.identifiers.Identifier; +import org.zwobble.couscous.ast.identifiers.Identifiers; import org.zwobble.couscous.types.Type; +import org.zwobble.couscous.types.TypeParameter; import java.util.List; import static java.util.Arrays.asList; import static org.zwobble.couscous.frontends.java.JavaTypes.typeOf; +import static org.zwobble.couscous.types.Types.erasure; import static org.zwobble.couscous.util.ExtraLists.eagerMap; import static org.zwobble.couscous.util.ExtraLists.list; @@ -17,26 +21,50 @@ class JavaMethods { static MethodSignature signature(IMethodBinding method) { ITypeBinding declaringClass = method.getDeclaringClass(); ITypeBinding erasedDeclaringClass = declaringClass.getErasure(); + IMethodBinding declaringMethod = method.getMethodDeclaration(); - List<Type> argumentTypes = eagerMap(asList(method.getParameterTypes()), JavaTypes::typeOf); - Type returnType = typeOf(method.getReturnType()); + MethodSignature unboundSignature = unboundSignature(method); - if (declaringClass.isEqualTo(erasedDeclaringClass)) { - return new MethodSignature(method.getName(), list(), argumentTypes, returnType); - } else { + if (!declaringMethod.isEqualTo(method)) { + return bind(unboundSignature(declaringMethod), unboundSignature); + } else if (!declaringClass.isEqualTo(erasedDeclaringClass)) { IMethodBinding[] erasedMethods = erasedDeclaringClass.getDeclaredMethods(); IMethodBinding erasedMethod = Iterables.getOnlyElement(Iterables.filter( asList(erasedMethods), m -> m.isSubsignature(method))); - return new MethodSignature( - method.getName(), - list(), - eagerMap( - argumentTypes, - asList(erasedMethod.getParameterTypes()), - (argumentType, erasedParameterType) -> JavaTypes.bind(typeOf(erasedParameterType), argumentType)), - JavaTypes.bind(typeOf(erasedMethod.getReturnType()), returnType)); + return bind(unboundSignature(erasedMethod), unboundSignature); + } else { + return unboundSignature; + } + } + + private static MethodSignature bind(MethodSignature genericSignature, MethodSignature concreteSignature) { + if (!genericSignature.getTypeParameters().isEmpty()) { + throw new UnsupportedOperationException(); } + return new MethodSignature( + concreteSignature.getName(), + list(), + eagerMap( + genericSignature.getArguments(), + concreteSignature.getArguments(), + JavaTypes::bind), + JavaTypes.bind(genericSignature.getReturnType(), concreteSignature.getReturnType())); + } + + private static MethodSignature unboundSignature(IMethodBinding method) { + List<TypeParameter> typeParameters = eagerMap( + asList(method.getTypeParameters()), + parameter -> new TypeParameter(identifierFor(method), parameter.getName())); + List<Type> argumentTypes = eagerMap(asList(method.getParameterTypes()), JavaTypes::typeOf); + Type returnType = typeOf(method.getReturnType()); + return new MethodSignature(method.getName(), typeParameters, argumentTypes, returnType); } + private static Identifier identifierFor(IMethodBinding method) { + // TODO: disambiguate overloads + return Identifiers.method( + Identifiers.forType(erasure(typeOf(method.getDeclaringClass()))), + method.getName()); + } } |
