changeset 7851:e25ad0220267

Codewriter now supports writing generic type hierarchies and wildcards. Added a method to resolve a common base type out of multiple types.
author Christian Humer <christian.humer@gmail.com>
date Mon, 25 Feb 2013 13:01:58 +0100
parents 85891f9c2197
children 9aea719e6e98
files graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/Utils.java
diffstat 1 files changed, 82 insertions(+), 11 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/Utils.java	Mon Feb 25 12:43:18 2013 +0100
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/Utils.java	Mon Feb 25 13:01:58 2013 +0100
@@ -47,6 +47,14 @@
         }
     }
 
+    public static TypeMirror boxType(ProcessorContext context, TypeMirror primitiveType) {
+        TypeMirror boxedType = primitiveType;
+        if (boxedType.getKind().isPrimitive()) {
+            boxedType = context.getEnvironment().getTypeUtils().boxedClass((PrimitiveType) boxedType).asType();
+        }
+        return boxedType;
+    }
+
     public static List<AnnotationMirror> collectAnnotations(ProcessorContext context, AnnotationMirror markerAnnotation, String elementName, Element element,
                     Class<? extends Annotation> annotationClass) {
         List<AnnotationMirror> result = Utils.getAnnotationValueList(markerAnnotation, elementName);
@@ -61,6 +69,42 @@
         return result;
     }
 
+    public static TypeMirror getCommonSuperType(ProcessorContext context, TypeMirror[] types) {
+        if (types.length == 0) {
+            return context.getType(Object.class);
+        }
+        TypeMirror prev = types[0];
+        for (int i = 1; i < types.length; i++) {
+            prev = getCommonSuperType(context, prev, types[i]);
+        }
+        return prev;
+    }
+
+    public static TypeMirror getCommonSuperType(ProcessorContext context, TypeMirror type1, TypeMirror type2) {
+        if (typeEquals(type1, type2)) {
+            return type1;
+        }
+        TypeElement element1 = fromTypeMirror(type1);
+        TypeElement element2 = fromTypeMirror(type2);
+        if (element1 == null || element2 == null) {
+            return context.getType(Object.class);
+        }
+
+        List<TypeElement> element1Types = getDirectSuperTypes(element1);
+        element1Types.add(0, element1);
+        List<TypeElement> element2Types = getDirectSuperTypes(element2);
+        element2Types.add(0, element2);
+
+        for (TypeElement superType1 : element1Types) {
+            for (TypeElement superType2 : element2Types) {
+                if (typeEquals(superType1.asType(), superType2.asType())) {
+                    return superType2.asType();
+                }
+            }
+        }
+        return context.getType(Object.class);
+    }
+
     public static String getReadableSignature(ExecutableElement method) {
         // TODO toString does not guarantee a good signature
         return method.toString();
@@ -146,31 +190,43 @@
             case LONG:
                 return "long";
             case DECLARED:
-                return getGenericName(fromTypeMirror(mirror));
+                return getDeclaredName((DeclaredType) mirror);
             case ARRAY:
                 return getSimpleName(((ArrayType) mirror).getComponentType()) + "[]";
             case VOID:
                 return "void";
+            case WILDCARD:
+                return getWildcardName((WildcardType) mirror);
             case TYPEVAR:
-                return ((TypeParameterElement) ((TypeVariable) mirror).asElement()).getSimpleName().toString();
+                return "?";
             default:
                 throw new RuntimeException("Unknown type specified " + mirror.getKind() + " mirror: " + mirror);
         }
     }
 
-    private static String getGenericName(TypeElement element) {
-        String simpleName = element.getSimpleName().toString();
+    private static String getWildcardName(WildcardType type) {
+        StringBuilder b = new StringBuilder();
+        if (type.getExtendsBound() != null) {
+            b.append("? extends ").append(getSimpleName(type.getExtendsBound()));
+        } else if (type.getSuperBound() != null) {
+            b.append("? super ").append(getSimpleName(type.getExtendsBound()));
+        }
+        return b.toString();
+    }
 
-        if (element.getTypeParameters().size() == 0) {
+    private static String getDeclaredName(DeclaredType element) {
+        String simpleName = element.asElement().getSimpleName().toString();
+
+        if (element.getTypeArguments().size() == 0) {
             return simpleName;
         }
 
         StringBuilder b = new StringBuilder(simpleName);
         b.append("<");
-        if (element.getTypeParameters().size() > 0) {
-            for (int i = 0; i < element.getTypeParameters().size(); i++) {
-                b.append("?");
-                if (i < element.getTypeParameters().size() - 1) {
+        if (element.getTypeArguments().size() > 0) {
+            for (int i = 0; i < element.getTypeArguments().size(); i++) {
+                b.append(getSimpleName(element.getTypeArguments().get(i)));
+                if (i < element.getTypeArguments().size() - 1) {
                     b.append(", ");
                 }
             }
@@ -282,6 +338,19 @@
         return null;
     }
 
+    public static List<TypeElement> getDirectSuperTypes(TypeElement element) {
+        List<TypeElement> types = new ArrayList<>();
+        if (element.getSuperclass() != null) {
+            TypeElement superElement = fromTypeMirror(element.getSuperclass());
+            if (superElement != null) {
+                types.add(superElement);
+                types.addAll(getDirectSuperTypes(superElement));
+            }
+        }
+
+        return types;
+    }
+
     public static List<TypeElement> getSuperTypes(TypeElement element) {
         List<TypeElement> types = new ArrayList<>();
         List<TypeElement> superTypes = null;
@@ -468,8 +537,10 @@
             for (int i = 0; i < params.length; i++) {
                 TypeMirror param1 = params[i];
                 TypeMirror param2 = method.getParameters().get(i).asType();
-                if (!getQualifiedName(param1).equals(getQualifiedName(param2))) {
-                    continue method;
+                if (param1.getKind() != TypeKind.TYPEVAR && param2.getKind() != TypeKind.TYPEVAR) {
+                    if (!getQualifiedName(param1).equals(getQualifiedName(param2))) {
+                        continue method;
+                    }
                 }
             }
             return method;