# HG changeset patch # User Christian Humer # Date 1377790795 -7200 # Node ID 4830676526e3dcd3fe76b2e6bd53a8ecccdcd25c # Parent 3d618420a4b6fd4a6a4e732220db1d959b0847ea Truffle-DSL: added infrastructure to assert for DSL error messages. diff -r 3d618420a4b6 -r 4830676526e3 graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/CompilerErrorTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/CompilerErrorTest.java Thu Aug 29 17:39:55 2013 +0200 @@ -0,0 +1,57 @@ +/* + * 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. + * + * 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.truffle.api.dsl.test; + +import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode; + +public class CompilerErrorTest { + + abstract static class Visiblity01 extends ValueNode { + + @Specialization + @SuppressWarnings("static-method") + @ExpectError("Method annotated with @Specialization must not be private.") + private Object s() { + return null; + } + + } + + @ExpectError("Nodes containing the @Specialization annotation cannot be private.") + private abstract static class Visiblity02 extends ValueNode { + + @Specialization + public Object s() { + return null; + } + + } + + // assert no error + @ExpectError({}) + private abstract static class Visiblity03 extends ValueNode { + + } + +} diff -r 3d618420a4b6 -r 4830676526e3 graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/ExpectError.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/ExpectError.java Thu Aug 29 17:39:55 2013 +0200 @@ -0,0 +1,38 @@ +/* + * 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.truffle.api.dsl; + +import java.lang.annotation.*; + +/** + * This annotation is internally known by the dsl processor and used to expect errors for testing + * purposes. This is not part of public API. + */ +@Retention(RetentionPolicy.RUNTIME) +public @interface ExpectError { + + String[] value(); + +} diff -r 3d618420a4b6 -r 4830676526e3 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/AbstractParser.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/AbstractParser.java Thu Aug 29 14:28:43 2013 +0200 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/AbstractParser.java Thu Aug 29 17:39:55 2013 +0200 @@ -65,7 +65,7 @@ return null; } - model.emitMessages((TypeElement) element, log); + model.emitMessages(context, (TypeElement) element, log); return filterErrorElements(model); } catch (CompileErrorException e) { log.message(Kind.WARNING, element, null, null, "The truffle processor could not parse class due to error: %s", e.getMessage()); diff -r 3d618420a4b6 -r 4830676526e3 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/TruffleTypes.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/TruffleTypes.java Thu Aug 29 14:28:43 2013 +0200 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/TruffleTypes.java Thu Aug 29 17:39:55 2013 +0200 @@ -30,6 +30,7 @@ import com.oracle.truffle.api.*; import com.oracle.truffle.api.CompilerDirectives.*; +import com.oracle.truffle.api.dsl.*; import com.oracle.truffle.api.frame.*; import com.oracle.truffle.api.nodes.*; import com.oracle.truffle.api.nodes.Node.Child; @@ -56,6 +57,7 @@ private final TypeMirror compilerAsserts; private final DeclaredType slowPath; private final DeclaredType truffleOptions; + private final TypeElement expectError; private final List errors = new ArrayList<>(); @@ -74,6 +76,11 @@ nodeInfoKind = getRequired(context, NodeInfo.Kind.class); slowPath = getRequired(context, SlowPath.class); truffleOptions = getRequired(context, TruffleOptions.class); + expectError = (TypeElement) getRequired(context, ExpectError.class).asElement(); + } + + public TypeElement getExpectError() { + return expectError; } public DeclaredType getNodeInfoAnnotation() { diff -r 3d618420a4b6 -r 4830676526e3 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/Utils.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/Utils.java Thu Aug 29 14:28:43 2013 +0200 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/Utils.java Thu Aug 29 17:39:55 2013 +0200 @@ -755,6 +755,10 @@ public static AnnotationMirror findAnnotationMirror(ProcessingEnvironment processingEnv, List mirrors, Class annotationClass) { TypeElement expectedAnnotationType = processingEnv.getElementUtils().getTypeElement(annotationClass.getCanonicalName()); + return findAnnotationMirror(mirrors, expectedAnnotationType); + } + + public static AnnotationMirror findAnnotationMirror(List mirrors, TypeElement expectedAnnotationType) { for (AnnotationMirror mirror : mirrors) { DeclaredType annotationType = mirror.getAnnotationType(); TypeElement actualAnnotationType = (TypeElement) annotationType.asElement(); diff -r 3d618420a4b6 -r 4830676526e3 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeParser.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeParser.java Thu Aug 29 14:28:43 2013 +0200 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeParser.java Thu Aug 29 17:39:55 2013 +0200 @@ -30,6 +30,8 @@ import javax.lang.model.util.*; import javax.tools.Diagnostic.Kind; +import org.omg.CORBA.*; + import com.oracle.truffle.api.dsl.*; import com.oracle.truffle.api.nodes.*; import com.oracle.truffle.dsl.processor.*; @@ -199,6 +201,10 @@ } for (NodeData splittedNode : nodes) { + if (templateType.getModifiers().contains(Modifier.PRIVATE) && splittedNode.getSpecializations().size() > 0) { + splittedNode.addError("Nodes containing the @%s annotation cannot be private.", Specialization.class.getSimpleName()); + } + finalizeSpecializations(elements, splittedNode); verifyNode(splittedNode, elements); createPolymorphicSpecializations(splittedNode); diff -r 3d618420a4b6 -r 4830676526e3 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/SpecializationMethodParser.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/SpecializationMethodParser.java Thu Aug 29 14:28:43 2013 +0200 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/SpecializationMethodParser.java Thu Aug 29 17:39:55 2013 +0200 @@ -57,7 +57,6 @@ int order = Utils.getAnnotationValue(Integer.class, method.getMarkerAnnotation(), "order"); if (order < 0 && order != Specialization.DEFAULT_ORDER) { method.addError("Invalid order attribute %d. The value must be >= 0 or the default value."); - return null; } AnnotationValue rewriteValue = Utils.getAnnotationValue(method.getMarkerAnnotation(), "rewriteOn"); diff -r 3d618420a4b6 -r 4830676526e3 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/MessageContainer.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/MessageContainer.java Thu Aug 29 14:28:43 2013 +0200 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/MessageContainer.java Thu Aug 29 17:39:55 2013 +0200 @@ -51,13 +51,29 @@ public abstract Element getMessageElement(); - public final void emitMessages(TypeElement baseElement, Log log) { - emitMessagesImpl(baseElement, log, new HashSet()); + public final void emitMessages(ProcessorContext context, TypeElement baseElement, Log log) { + emitMessagesImpl(context, baseElement, log, new HashSet()); } - private void emitMessagesImpl(TypeElement baseElement, Log log, Set visitedSinks) { + private void emitMessagesImpl(ProcessorContext context, TypeElement baseElement, Log log, Set visitedSinks) { + TypeElement expectError = context.getTruffleTypes().getExpectError(); + if (expectError != null) { + Element element = getMessageElement(); + AnnotationMirror mirror = Utils.findAnnotationMirror(element.getAnnotationMirrors(), expectError); + if (mirror != null) { + List values = Utils.getAnnotationValueList(String.class, mirror, "value"); + if (values == null) { + values = Collections.emptyList(); + } + List msgs = getMessages(); + if (values.size() != msgs.size()) { + log.message(Kind.ERROR, element, mirror, Utils.getAnnotationValue(mirror, "value"), String.format("Error count expected %s but was %s.", values.size(), msgs.size())); + } + } + } + for (Message message : getMessages()) { - emitDefault(baseElement, log, message); + emitDefault(context, baseElement, log, message); } for (MessageContainer sink : findChildContainers()) { @@ -66,18 +82,46 @@ } visitedSinks.add(sink); - sink.emitMessagesImpl(baseElement, log, visitedSinks); + sink.emitMessagesImpl(context, baseElement, log, visitedSinks); } } - private void emitDefault(TypeElement baseType, Log log, Message message) { + private void emitDefault(ProcessorContext context, TypeElement baseType, Log log, Message message) { + Kind kind = message.getKind(); + + Element messageElement = getMessageElement(); + AnnotationMirror messageAnnotation = getMessageAnnotation(); + AnnotationValue messageValue = getMessageAnnotationValue(); + if (message.getAnnotationValue() != null) { + messageValue = message.getAnnotationValue(); + } + + String text = message.getText(); + TypeElement rootEnclosing = Utils.findRootEnclosingType(getMessageElement()); - if (rootEnclosing != null && Utils.typeEquals(baseType.asType(), rootEnclosing.asType()) && this == message.getOriginalContainer()) { - log.message(message.getKind(), getMessageElement(), getMessageAnnotation(), getMessageAnnotationValue(), message.getText()); - } else { + if (rootEnclosing == null || !Utils.typeEquals(baseType.asType(), rootEnclosing.asType()) || this != message.getOriginalContainer()) { + // redirect message MessageContainer original = message.getOriginalContainer(); - log.message(message.getKind(), baseType, null, null, wrapText(original.getMessageElement(), original.getMessageAnnotation(), message.getText())); + messageElement = baseType; + messageAnnotation = null; + messageValue = null; + text = wrapText(original.getMessageElement(), original.getMessageAnnotation(), message.getText()); } + + TypeElement expectError = context.getTruffleTypes().getExpectError(); + if (expectError != null) { + AnnotationMirror mirror = Utils.findAnnotationMirror(messageElement.getAnnotationMirrors(), expectError); + if (mirror != null) { + List expectedTexts = Utils.getAnnotationValueList(String.class, mirror, "value"); + if (!expectedTexts.contains(text)) { + log.message(kind, messageElement, mirror, Utils.getAnnotationValue(mirror, "value"), String.format("Message expected one of '%s' but was '%s'.", expectedTexts, text)); + } else { + return; + } + } + } + + log.message(kind, messageElement, messageAnnotation, messageValue, text); } private static String wrapText(Element element, AnnotationMirror mirror, String text) { diff -r 3d618420a4b6 -r 4830676526e3 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/TemplateMethodParser.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/TemplateMethodParser.java Thu Aug 29 14:28:43 2013 +0200 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/TemplateMethodParser.java Thu Aug 29 17:39:55 2013 +0200 @@ -43,7 +43,7 @@ protected final T template; private boolean emitErrors = true; - private boolean parseNullOnError = true; + private boolean parseNullOnError = false; public TemplateMethodParser(ProcessorContext context, T template) { this.template = template; @@ -104,7 +104,8 @@ E parsedMethod = parse(method, mirror); if (method.getModifiers().contains(Modifier.PRIVATE) && emitErrors) { - parsedMethod.addError("Method must not be private."); + parsedMethod.addError("Method annotated with @%s must not be private.", getAnnotationType().getSimpleName()); + parsedMethods.add(parsedMethod); valid = false; continue; } diff -r 3d618420a4b6 -r 4830676526e3 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeSystemParser.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeSystemParser.java Thu Aug 29 14:28:43 2013 +0200 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeSystemParser.java Thu Aug 29 17:39:55 2013 +0200 @@ -37,7 +37,7 @@ public class TypeSystemParser extends TemplateParser { - public static final List> ANNOTATIONS = Arrays.asList(TypeSystem.class); + public static final List> ANNOTATIONS = Arrays.asList(TypeSystem.class, ExpectError.class); public TypeSystemParser(ProcessorContext c) { super(c);