changeset 16820:1a8d95626af7

annotate generated Node classes with @GeneratedNode; improved error messages in @NodeInfo annotation processor
author Doug Simon <doug.simon@oracle.com>
date Wed, 13 Aug 2014 18:23:04 +0200
parents 16f933f2fd59
children 216ac26009a2
files graal/com.oracle.graal.graph.processor/src/com/oracle/graal/graph/processor/GraphNodeGenerator.java graal/com.oracle.graal.graph.processor/src/com/oracle/graal/graph/processor/GraphNodeParser.java graal/com.oracle.graal.graph.processor/src/com/oracle/graal/graph/processor/GraphNodeProcessor.java graal/com.oracle.graal.graph/src/com/oracle/graal/graph/GeneratedNode.java
diffstat 4 files changed, 104 insertions(+), 81 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.graph.processor/src/com/oracle/graal/graph/processor/GraphNodeGenerator.java	Wed Aug 13 14:06:36 2014 +0200
+++ b/graal/com.oracle.graal.graph.processor/src/com/oracle/graal/graph/processor/GraphNodeGenerator.java	Wed Aug 13 18:23:04 2014 +0200
@@ -26,11 +26,16 @@
 
 import javax.annotation.processing.*;
 import javax.lang.model.element.*;
+import javax.lang.model.type.*;
 import javax.lang.model.util.*;
 
+import com.oracle.graal.graph.*;
 import com.oracle.truffle.dsl.processor.java.*;
 import com.oracle.truffle.dsl.processor.java.model.*;
 
+/**
+ * Generates the source code for a {@link Node} class.
+ */
 public class GraphNodeGenerator {
 
     private final ProcessingEnvironment processingEnv;
@@ -67,6 +72,11 @@
             nodeGenElement.add(createSuperConstructor(nodeGenElement, constructor));
         }
 
+        DeclaredType generatedNode = (DeclaredType) ElementUtils.getType(processingEnv, GeneratedNode.class);
+        CodeAnnotationMirror generatedByMirror = new CodeAnnotationMirror(generatedNode);
+        generatedByMirror.setElementValue(generatedByMirror.findExecutableElement("value"), new CodeAnnotationValue(typeElement.asType()));
+        nodeGenElement.getAnnotationMirrors().add(generatedByMirror);
+
         nodeGenElement.add(createDummyExampleMethod());
 
         compilationUnit.add(nodeGenElement);
--- a/graal/com.oracle.graal.graph.processor/src/com/oracle/graal/graph/processor/GraphNodeParser.java	Wed Aug 13 14:06:36 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,56 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.graph.processor;
-
-import java.lang.annotation.*;
-
-import javax.annotation.processing.*;
-import javax.lang.model.element.*;
-
-import com.oracle.graal.graph.*;
-
-public class GraphNodeParser {
-
-    private final ProcessingEnvironment processingEnv;
-
-    public GraphNodeParser(ProcessingEnvironment processingEnv) {
-        this.processingEnv = processingEnv;
-    }
-
-    protected GraphNode parse(TypeElement element, NodeInfo nodeInfo) {
-        if (element.getModifiers().contains(Modifier.FINAL)) {
-            // TODO fail?
-            return null;
-        }
-        return new GraphNode(element, nodeInfo);
-    }
-
-    public ProcessingEnvironment getProcessingEnv() {
-        return processingEnv;
-    }
-
-    public Class<? extends Annotation> getAnnotationType() {
-        return NodeInfo.class;
-    }
-
-}
--- a/graal/com.oracle.graal.graph.processor/src/com/oracle/graal/graph/processor/GraphNodeProcessor.java	Wed Aug 13 14:06:36 2014 +0200
+++ b/graal/com.oracle.graal.graph.processor/src/com/oracle/graal/graph/processor/GraphNodeProcessor.java	Wed Aug 13 18:23:04 2014 +0200
@@ -22,12 +22,15 @@
  */
 package com.oracle.graal.graph.processor;
 
+import java.io.*;
 import java.util.*;
 
 import javax.annotation.processing.*;
 import javax.lang.model.*;
 import javax.lang.model.element.*;
 import javax.lang.model.type.*;
+import javax.lang.model.util.*;
+import javax.tools.Diagnostic.Kind;
 
 import com.oracle.graal.graph.*;
 import com.oracle.truffle.dsl.processor.*;
@@ -38,6 +41,25 @@
 @SupportedSourceVersion(SourceVersion.RELEASE_8)
 @SupportedAnnotationTypes({"com.oracle.graal.graph.NodeInfo"})
 public class GraphNodeProcessor extends AbstractProcessor {
+    @Override
+    public SourceVersion getSupportedSourceVersion() {
+        return SourceVersion.latest();
+    }
+
+    private void errorMessage(Element element, String format, Object... args) {
+        processingEnv.getMessager().printMessage(Kind.ERROR, String.format(format, args), element);
+    }
+
+    /**
+     * Bugs in an annotation processor can cause silent failure so try to report any exception
+     * throws as errors.
+     */
+    private void reportException(Element element, Throwable t) {
+        StringWriter buf = new StringWriter();
+        t.printStackTrace(new PrintWriter(buf));
+        buf.toString();
+        errorMessage(element, "Exception thrown during processing: %s", buf.toString());
+    }
 
     @Override
     public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
@@ -45,38 +67,45 @@
             return false;
         }
 
-        GraphNodeParser parser = new GraphNodeParser(processingEnv);
         GraphNodeGenerator gen = new GraphNodeGenerator(processingEnv);
+        Types types = processingEnv.getTypeUtils();
+        Elements elements = processingEnv.getElementUtils();
+
+        TypeMirror nodeType = elements.getTypeElement(Node.class.getName()).asType();
 
-        for (Element annotatedElement : roundEnv.getElementsAnnotatedWith(parser.getAnnotationType())) {
-            if (annotatedElement.getKind() != ElementKind.CLASS) {
-                // TODO fail?
-                continue;
-            }
+        for (Element element : roundEnv.getElementsAnnotatedWith(NodeInfo.class)) {
+            try {
+                if (!types.isSubtype(element.asType(), nodeType)) {
+                    errorMessage(element, "%s can only be applied to %s subclasses", NodeInfo.class.getSimpleName(), Node.class.getSimpleName());
+                    continue;
+                }
 
-            NodeInfo nodeInfo = annotatedElement.getAnnotation(NodeInfo.class);
-            if (nodeInfo == null) {
-                // TODO assert nodeInfo != null?
-                continue;
-            }
+                NodeInfo nodeInfo = element.getAnnotation(NodeInfo.class);
+                if (nodeInfo == null) {
+                    errorMessage(element, "Cannot get %s annotation from annotated element", NodeInfo.class.getSimpleName());
+                    continue;
+                }
 
-            TypeElement typeElement = (TypeElement) annotatedElement;
-            GraphNode graphNode = parser.parse(typeElement, nodeInfo);
-            if (graphNode == null) {
-                // TODO fail?`
-                continue;
-            }
+                TypeElement typeElement = (TypeElement) element;
+
+                if (typeElement.getModifiers().contains(Modifier.FINAL)) {
+                    errorMessage(element, "%s annotated class cannot be final", NodeInfo.class.getSimpleName());
+                    continue;
+                }
 
-            CodeCompilationUnit unit = gen.process(graphNode);
-            unit.setGeneratorElement(typeElement);
+                GraphNode graphNode = new GraphNode(typeElement, nodeInfo);
+                CodeCompilationUnit unit = gen.process(graphNode);
+                unit.setGeneratorElement(typeElement);
 
-            DeclaredType overrideType = (DeclaredType) ElementUtils.getType(processingEnv, Override.class);
-            DeclaredType unusedType = (DeclaredType) ElementUtils.getType(processingEnv, SuppressWarnings.class);
-            unit.accept(new GenerateOverrideVisitor(overrideType), null);
-            unit.accept(new FixWarningsVisitor(processingEnv, unusedType, overrideType), null);
-            unit.accept(new CodeWriter(processingEnv, typeElement), null);
+                DeclaredType overrideType = (DeclaredType) ElementUtils.getType(processingEnv, Override.class);
+                DeclaredType unusedType = (DeclaredType) ElementUtils.getType(processingEnv, SuppressWarnings.class);
+                unit.accept(new GenerateOverrideVisitor(overrideType), null);
+                unit.accept(new FixWarningsVisitor(processingEnv, unusedType, overrideType), null);
+                unit.accept(new CodeWriter(processingEnv, typeElement), null);
+            } catch (Throwable t) {
+                reportException(element, t);
+            }
         }
         return false;
     }
-
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/GeneratedNode.java	Wed Aug 13 18:23:04 2014 +0200
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.graph;
+
+import java.lang.annotation.*;
+
+/**
+ * Denotes a {@link Node} class derived from a {@link NodeInfo} annotated {@link Node} type.
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.TYPE})
+public @interface GeneratedNode {
+
+    /**
+     * The {@link Node} class from which the annotated type was generated.
+     */
+    Class<?> value();
+}