# HG changeset patch # User Doug Simon # Date 1407946984 -7200 # Node ID 1a8d95626af78696562e27dab36e756fcd08fc19 # Parent 16f933f2fd59de044ed405a002ee976fed445d02 annotate generated Node classes with @GeneratedNode; improved error messages in @NodeInfo annotation processor diff -r 16f933f2fd59 -r 1a8d95626af7 graal/com.oracle.graal.graph.processor/src/com/oracle/graal/graph/processor/GraphNodeGenerator.java --- 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); diff -r 16f933f2fd59 -r 1a8d95626af7 graal/com.oracle.graal.graph.processor/src/com/oracle/graal/graph/processor/GraphNodeParser.java --- 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 getAnnotationType() { - return NodeInfo.class; - } - -} diff -r 16f933f2fd59 -r 1a8d95626af7 graal/com.oracle.graal.graph.processor/src/com/oracle/graal/graph/processor/GraphNodeProcessor.java --- 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 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; } - } diff -r 16f933f2fd59 -r 1a8d95626af7 graal/com.oracle.graal.graph/src/com/oracle/graal/graph/GeneratedNode.java --- /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(); +}