diff graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeSystemParser.java @ 8252:0905d796944a

Refactored codegen error model to make error redirection a lot easier.
author Christian Humer <christian.humer@gmail.com>
date Wed, 13 Mar 2013 19:58:28 +0100
parents c4c3f50fa9c2
children 8b2573c8d47f
line wrap: on
line diff
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeSystemParser.java	Wed Mar 13 11:32:43 2013 +0100
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeSystemParser.java	Wed Mar 13 19:58:28 2013 +0100
@@ -52,27 +52,39 @@
     protected TypeSystemData parse(Element element, AnnotationMirror mirror) {
         TypeElement templateType = (TypeElement) element;
         AnnotationMirror templateTypeAnnotation = mirror;
+        TypeSystemData typeSystem = new TypeSystemData(templateType, templateTypeAnnotation);
 
-        if (!verifyTemplateType(templateType, templateTypeAnnotation)) {
-            return null;
+        // annotation type on class path!?
+        TypeElement annotationTypeElement = processingEnv.getElementUtils().getTypeElement(getAnnotationType().getCanonicalName());
+        if (annotationTypeElement == null) {
+            typeSystem.addError("Required class %s is not on the classpath.", getAnnotationType().getName());
+        }
+        if (templateType.getModifiers().contains(Modifier.PRIVATE)) {
+            typeSystem.addError("A @%s must have at least package protected visibility.", getAnnotationType().getName());
         }
 
-        TypeData[] types = parseTypes(templateType, templateTypeAnnotation);
-        if (types == null) {
-            return null;
+        if (templateType.getModifiers().contains(Modifier.FINAL)) {
+            typeSystem.addError("The @%s must not be final.", getAnnotationType().getName());
+        }
+        if (typeSystem.hasErrors()) {
+            return typeSystem;
+        }
+
+        typeSystem.setTypes(parseTypes(typeSystem));
+        if (typeSystem.getTypes() == null) {
+            return typeSystem;
         }
 
         TypeMirror genericType = context.getType(Object.class);
-        TypeData voidType = new TypeData(templateType, templateTypeAnnotation, context.getType(void.class), context.getType(Void.class));
-
-        TypeSystemData typeSystem = new TypeSystemData(templateType, templateTypeAnnotation, types, genericType, voidType);
+        TypeData voidType = new TypeData(typeSystem, null, context.getType(void.class), context.getType(Void.class));
 
-        if (!verifyExclusiveMethodAnnotation(templateType, TypeCast.class, TypeCheck.class)) {
-            return null;
-        }
+        typeSystem.setGenericType(genericType);
+        typeSystem.setVoidType(voidType);
+
+        verifyExclusiveMethodAnnotation(typeSystem, TypeCast.class, TypeCheck.class);
 
         List<Element> elements = new ArrayList<>(context.getEnvironment().getElementUtils().getAllMembers(templateType));
-        typeSystem.setExtensionElements(getExtensionParser().parseAll(templateType, elements));
+        typeSystem.setExtensionElements(getExtensionParser().parseAll(typeSystem, elements));
         if (typeSystem.getExtensionElements() != null) {
             elements.addAll(typeSystem.getExtensionElements());
         }
@@ -81,7 +93,7 @@
         List<TypeCheckData> checks = new TypeCheckParser(context, typeSystem).parse(elements);
 
         if (casts == null || checks == null) {
-            return null;
+            return typeSystem;
         }
 
         for (TypeCheckData check : checks) {
@@ -92,24 +104,15 @@
             cast.getTargetType().addTypeCast(cast);
         }
 
-        if (!verifyGenericTypeChecksAndCasts(types)) {
-            return null;
-        }
-
-        if (!verifyMethodSignatures(element, types)) {
-            return null;
-        }
-
-        if (!verifyNamesUnique(templateType, templateTypeAnnotation, types)) {
-            return null;
-        }
+        verifyGenericTypeChecksAndCasts(typeSystem);
+        verifyMethodSignatures(typeSystem);
+        verifyNamesUnique(typeSystem);
 
         return typeSystem;
     }
 
-    private boolean verifyGenericTypeChecksAndCasts(TypeData[] types) {
-        boolean valid = true;
-        for (TypeData type : types) {
+    private static void verifyGenericTypeChecksAndCasts(TypeSystemData typeSystem) {
+        for (TypeData type : typeSystem.getTypes()) {
             if (!type.getTypeChecks().isEmpty()) {
                 boolean hasGeneric = false;
                 for (TypeCheckData typeCheck : type.getTypeChecks()) {
@@ -119,10 +122,9 @@
                     }
                 }
                 if (!hasGeneric) {
-                    log.error(type.getTypeSystem().getTemplateType(), "No generic but specific @%s method %s for type %s specified. "
-                                    + "Specify a generic @%s method with parameter type %s to resolve this.", TypeCheck.class.getSimpleName(), TypeSystemCodeGenerator.isTypeMethodName(type),
-                                    Utils.getSimpleName(type.getBoxedType()), TypeCheck.class.getSimpleName(), Object.class.getSimpleName());
-                    valid = false;
+                    type.addError("No generic but specific @%s method %s for type %s specified. " + "Specify a generic @%s method with parameter type %s to resolve this.",
+                                    TypeCheck.class.getSimpleName(), TypeSystemCodeGenerator.isTypeMethodName(type), Utils.getSimpleName(type.getBoxedType()), TypeCheck.class.getSimpleName(),
+                                    Object.class.getSimpleName());
                 }
             }
             if (!type.getTypeCasts().isEmpty()) {
@@ -134,60 +136,55 @@
                     }
                 }
                 if (!hasGeneric) {
-                    log.error(type.getTypeSystem().getTemplateType(), "No generic but specific @%s method %s for type %s specified. "
-                                    + "Specify a generic @%s method with parameter type %s to resolve this.", TypeCast.class.getSimpleName(), TypeSystemCodeGenerator.asTypeMethodName(type),
-                                    Utils.getSimpleName(type.getBoxedType()), TypeCast.class.getSimpleName(), Object.class.getSimpleName());
-                    valid = false;
+                    type.addError("No generic but specific @%s method %s for type %s specified. " + "Specify a generic @%s method with parameter type %s to resolve this.",
+                                    TypeCast.class.getSimpleName(), TypeSystemCodeGenerator.asTypeMethodName(type), Utils.getSimpleName(type.getBoxedType()), TypeCast.class.getSimpleName(),
+                                    Object.class.getSimpleName());
                 }
             }
         }
-        return valid;
     }
 
-    private TypeData[] parseTypes(TypeElement templateType, AnnotationMirror templateTypeAnnotation) {
-        List<TypeMirror> typeMirrors = Utils.getAnnotationValueList(TypeMirror.class, templateTypeAnnotation, "value");
-        if (typeMirrors.size() == 0) {
-            log.error(templateType, templateTypeAnnotation, "At least one type must be defined.");
-            return null;
+    private List<TypeData> parseTypes(TypeSystemData typeSystem) {
+        List<TypeData> types = new ArrayList<>();
+        List<TypeMirror> typeMirrors = Utils.getAnnotationValueList(TypeMirror.class, typeSystem.getTemplateTypeAnnotation(), "value");
+        if (typeMirrors.isEmpty()) {
+            typeSystem.addError("At least one type must be defined.");
+            return types;
         }
 
-        final AnnotationValue annotationValue = Utils.getAnnotationValue(templateTypeAnnotation, "value");
+        final AnnotationValue annotationValue = Utils.getAnnotationValue(typeSystem.getTemplateTypeAnnotation(), "value");
         final TypeMirror objectType = context.getType(Object.class);
 
-        List<TypeData> types = new ArrayList<>();
         for (TypeMirror primitiveType : typeMirrors) {
+            TypeMirror boxedType = Utils.boxType(context, primitiveType);
+            TypeData typeData = new TypeData(typeSystem, annotationValue, primitiveType, boxedType);
 
             if (isPrimitiveWrapper(primitiveType)) {
-                log.error(templateType, templateTypeAnnotation, annotationValue, "Types must not contain primitive wrapper types.");
-                continue;
+                typeData.addError("Types must not contain primitive wrapper types.");
             }
 
-            TypeMirror boxedType = Utils.boxType(context, primitiveType);
-
             if (Utils.typeEquals(boxedType, objectType)) {
-                log.error(templateType, templateTypeAnnotation, annotationValue, "Types must not contain the generic type java.lang.Object.");
-                continue;
+                typeData.addError("Types must not contain the generic type java.lang.Object.");
             }
 
-            types.add(new TypeData(templateType, templateTypeAnnotation, primitiveType, boxedType));
+            types.add(typeData);
         }
 
-        verifyTypeOrder(templateType, templateTypeAnnotation, annotationValue, types);
+        verifyTypeOrder(types);
 
-        types.add(new TypeData(templateType, templateTypeAnnotation, objectType, objectType));
+        types.add(new TypeData(typeSystem, annotationValue, objectType, objectType));
 
-        return types.toArray(new TypeData[types.size()]);
+        return types;
     }
 
-    private void verifyTypeOrder(TypeElement templateType, AnnotationMirror templateTypeAnnotation, AnnotationValue annotationValue, List<TypeData> types) {
+    private static void verifyTypeOrder(List<TypeData> types) {
         Map<String, List<String>> invalidTypes = new HashMap<>();
 
         for (int i = types.size() - 1; i >= 0; i--) {
             TypeData typeData = types.get(i);
             TypeMirror type = typeData.getBoxedType();
             if (invalidTypes.containsKey(Utils.getQualifiedName(type))) {
-                log.error(templateType, templateTypeAnnotation, annotationValue, "Invalid type order. The type(s) %s are inherited from a earlier defined type %s.",
-                                invalidTypes.get(Utils.getQualifiedName(type)), Utils.getQualifiedName(type));
+                typeData.addError("Invalid type order. The type(s) %s are inherited from a earlier defined type %s.", invalidTypes.get(Utils.getQualifiedName(type)), Utils.getQualifiedName(type));
             }
             List<String> nextInvalidTypes = Utils.getQualifiedSuperTypeNames(Utils.fromTypeMirror(type));
             nextInvalidTypes.add(getQualifiedName(type));
@@ -216,19 +213,18 @@
         return false;
     }
 
-    private boolean verifyMethodSignatures(Element element, TypeData[] types) {
+    private void verifyMethodSignatures(TypeSystemData typeSystem) {
         Set<String> generatedIsMethodNames = new HashSet<>();
         Set<String> generatedAsMethodNames = new HashSet<>();
         Set<String> generatedExpectMethodNames = new HashSet<>();
 
-        for (TypeData typeData : types) {
+        for (TypeData typeData : typeSystem.getTypes()) {
             generatedIsMethodNames.add(TypeSystemCodeGenerator.isTypeMethodName(typeData));
             generatedAsMethodNames.add(TypeSystemCodeGenerator.asTypeMethodName(typeData));
             generatedExpectMethodNames.add(TypeSystemCodeGenerator.expectTypeMethodName(typeData));
         }
 
-        boolean valid = true;
-        List<ExecutableElement> methods = ElementFilter.methodsIn(element.getEnclosedElements());
+        List<ExecutableElement> methods = ElementFilter.methodsIn(typeSystem.getTemplateType().getEnclosedElements());
         for (ExecutableElement method : methods) {
             if (method.getModifiers().contains(Modifier.PRIVATE)) {
                 // will not conflict overridden methods
@@ -238,51 +234,48 @@
             }
             String methodName = method.getSimpleName().toString();
             if (generatedIsMethodNames.contains(methodName)) {
-                valid &= verifyIsMethod(method);
+                verifyIsMethod(typeSystem, method);
             } else if (generatedAsMethodNames.contains(methodName)) {
-                valid &= verifyAsMethod(method);
+                verifyAsMethod(typeSystem, method);
             } else if (generatedExpectMethodNames.contains(methodName)) {
-                valid &= verifyExpectMethod(method);
+                verifyExpectMethod(typeSystem);
             }
         }
-        return valid;
     }
 
-    private boolean verifyIsMethod(ExecutableElement method) {
+    private boolean verifyIsMethod(TypeSystemData typeSystem, ExecutableElement method) {
         AnnotationMirror mirror = Utils.findAnnotationMirror(processingEnv, method, TypeCheck.class);
         if (mirror == null) {
-            log.error(method, "Method starting with the pattern is${typeName} must be annotated with @%s.", TypeCheck.class.getSimpleName());
+            typeSystem.addError("Method starting with the pattern is${typeName} must be annotated with @%s.", TypeCheck.class.getSimpleName());
             return false;
         }
         return true;
     }
 
-    private boolean verifyAsMethod(ExecutableElement method) {
+    private boolean verifyAsMethod(TypeSystemData typeSystem, ExecutableElement method) {
         AnnotationMirror mirror = Utils.findAnnotationMirror(processingEnv, method, TypeCast.class);
         if (mirror == null) {
-            log.error(method, "Method starting with the pattern as${typeName} must be annotated with @%s.", TypeCast.class.getSimpleName());
+            typeSystem.addError("Method starting with the pattern as${typeName} must be annotated with @%s.", TypeCast.class.getSimpleName());
             return false;
         }
         return true;
     }
 
-    private boolean verifyExpectMethod(ExecutableElement method) {
-        log.error(method, "Method starting with the pattern expect${typeName} must not be declared manually.");
+    private static boolean verifyExpectMethod(TypeSystemData typeSystem) {
+        typeSystem.addError("Method starting with the pattern expect${typeName} must not be declared manually.");
         return false;
     }
 
-    private boolean verifyNamesUnique(TypeElement templateType, AnnotationMirror templateTypeAnnotation, TypeData[] types) {
-        boolean valid = true;
-        for (int i = 0; i < types.length; i++) {
-            for (int j = i + 1; j < types.length; j++) {
-                String name1 = Utils.getSimpleName(types[i].getBoxedType());
-                String name2 = Utils.getSimpleName(types[j].getBoxedType());
+    private static void verifyNamesUnique(TypeSystemData typeSystem) {
+        List<TypeData> types = typeSystem.getTypes();
+        for (int i = 0; i < types.size(); i++) {
+            for (int j = i + 1; j < types.size(); j++) {
+                String name1 = Utils.getSimpleName(types.get(i).getBoxedType());
+                String name2 = Utils.getSimpleName(types.get(j).getBoxedType());
                 if (name1.equalsIgnoreCase(name2)) {
-                    log.error(templateType, templateTypeAnnotation, "Two types result in the same name: %s, %s.", name1, name2);
-                    valid = false;
+                    typeSystem.addError("Two types result in the same name: %s, %s.", name1, name2);
                 }
             }
         }
-        return valid;
     }
 }