# HG changeset patch # User jlahoda # Date 1381499355 -7200 # Node ID f3bec12a63e777143336b19f33d94d20ab2e8624 # Parent 57913337d634e1f6f5f2aa4a90222f36830f5dfb 6278240: Exception from AnnotationValue.getValue() should list the found type not the required type Reviewed-by: darcy, jfranck, jjg diff -r 57913337d634 -r f3bec12a63e7 langtools/src/share/classes/com/sun/tools/javac/code/Type.java --- a/langtools/src/share/classes/com/sun/tools/javac/code/Type.java Thu Oct 10 23:26:56 2013 -0700 +++ b/langtools/src/share/classes/com/sun/tools/javac/code/Type.java Fri Oct 11 15:49:15 2013 +0200 @@ -165,6 +165,12 @@ return lb.toList(); } + /**For ErrorType, returns the original type, otherwise returns the type itself. + */ + public Type getOriginalType() { + return this; + } + public R accept(Type.Visitor v, S s) { return v.visitType(this, s); } /** Define a type given its tag and type symbol diff -r 57913337d634 -r f3bec12a63e7 langtools/src/share/classes/com/sun/tools/javac/comp/Annotate.java --- a/langtools/src/share/classes/com/sun/tools/javac/comp/Annotate.java Thu Oct 10 23:26:56 2013 -0700 +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Annotate.java Fri Oct 11 15:49:15 2013 +0200 @@ -37,6 +37,7 @@ import static com.sun.tools.javac.code.TypeTag.ARRAY; import static com.sun.tools.javac.code.TypeTag.CLASS; import static com.sun.tools.javac.tree.JCTree.Tag.*; +import javax.lang.model.type.ErrorType; /** Enter annotations on symbols. Annotations accumulate in a queue, * which is processed at the top level of any set of recursive calls @@ -310,7 +311,6 @@ Attribute enterAttributeValue(Type expected, JCExpression tree, Env env) { - Type original = expected; //first, try completing the attribution value sym - if a completion //error is thrown, we should recover gracefully, and display an //ordinary resolution diagnostic. @@ -351,7 +351,7 @@ l.head, env); } - return new Attribute.Error(original); + return new Attribute.Error(syms.errType); } if ((expected.tsym.flags() & Flags.ANNOTATION) != 0) { if (tree.hasTag(ANNOTATION)) { @@ -365,12 +365,12 @@ if (!expected.isErroneous()) log.error(tree.pos(), "annotation.not.valid.for.type", expected); enterAnnotation((JCAnnotation)tree, syms.errType, env); - return new Attribute.Error(original); + return new Attribute.Error(((JCAnnotation)tree).annotationType.type); } if (expected.isPrimitive() || types.isSameType(expected, syms.stringType)) { Type result = attr.attribExpr(tree, env, expected); if (result.isErroneous()) - return new Attribute.Error(expected); + return new Attribute.Error(result.getOriginalType()); if (result.constValue() == null) { log.error(tree.pos(), "attribute.value.must.be.constant"); return new Attribute.Error(expected); @@ -381,14 +381,15 @@ if (expected.tsym == syms.classType.tsym) { Type result = attr.attribExpr(tree, env, expected); if (result.isErroneous()) { - // Does it look like a class literal? - if (TreeInfo.name(tree) == names._class) { + // Does it look like an unresolved class literal? + if (TreeInfo.name(tree) == names._class && + ((JCFieldAccess) tree).selected.type.isErroneous()) { Name n = (((JCFieldAccess) tree).selected).type.tsym.flatName(); return new Attribute.UnresolvedClass(expected, types.createErrorType(n, syms.unknownSymbol, syms.classType)); } else { - return new Attribute.Error(expected); + return new Attribute.Error(result.getOriginalType()); } } @@ -396,21 +397,21 @@ // at the tree level if (TreeInfo.name(tree) != names._class) { log.error(tree.pos(), "annotation.value.must.be.class.literal"); - return new Attribute.Error(expected); + return new Attribute.Error(syms.errType); } return new Attribute.Class(types, (((JCFieldAccess) tree).selected).type); } if (expected.hasTag(CLASS) && (expected.tsym.flags() & Flags.ENUM) != 0) { - attr.attribExpr(tree, env, expected); + Type result = attr.attribExpr(tree, env, expected); Symbol sym = TreeInfo.symbol(tree); if (sym == null || TreeInfo.nonstaticSelect(tree) || sym.kind != Kinds.VAR || (sym.flags() & Flags.ENUM) == 0) { log.error(tree.pos(), "enum.annotation.must.be.enum.constant"); - return new Attribute.Error(expected); + return new Attribute.Error(result.getOriginalType()); } VarSymbol enumerator = (VarSymbol) sym; return new Attribute.Enum(expected, enumerator); diff -r 57913337d634 -r f3bec12a63e7 langtools/src/share/classes/com/sun/tools/javac/comp/MemberEnter.java --- a/langtools/src/share/classes/com/sun/tools/javac/comp/MemberEnter.java Thu Oct 10 23:26:56 2013 -0700 +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/MemberEnter.java Fri Oct 11 15:49:15 2013 +0200 @@ -1379,7 +1379,7 @@ if (!t.hasTag(ERROR)) return t; - return new ErrorType(((ErrorType) t).getOriginalType(), t.tsym) { + return new ErrorType(t.getOriginalType(), t.tsym) { private Type modelType; @Override diff -r 57913337d634 -r f3bec12a63e7 langtools/test/tools/javac/processing/errors/EnsureAnnotationTypeMismatchException/Processor.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/processing/errors/EnsureAnnotationTypeMismatchException/Processor.java Fri Oct 11 15:49:15 2013 +0200 @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2013, 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. + */ + +import java.io.IOException; +import java.io.Writer; +import java.lang.annotation.*; +import java.util.Set; +import javax.annotation.processing.*; +import javax.lang.model.element.*; +import javax.lang.model.util.ElementFilter; +import javax.tools.*; +import com.sun.tools.javac.util.Assert; + +public class Processor extends JavacTestingAbstractProcessor { + + private boolean seenGenerated; + + @Override + public boolean process(Set annotations, RoundEnvironment roundEnv) { + for (Element e : roundEnv.getElementsAnnotatedWith(Gen.class)) { + Gen gen = e.getAnnotation(Gen.class); + try { + JavaFileObject source = processingEnv.getFiler().createSourceFile(gen.fileName()); + + try (Writer out = source.openWriter()) { + out.write(gen.content()); + } + } catch (IOException ex) { + throw new IllegalStateException(ex); + } + } + + TypeElement generated = processingEnv.getElementUtils().getTypeElement("Generated"); + + if (generated != null) { + Check check = ElementFilter.methodsIn(generated.getEnclosedElements()).get(0).getAnnotation(Check.class); + + checkCorrectException(check::classValue, "java.lang.Class"); + checkCorrectException(check::intConstValue, "boolean"); + checkCorrectException(check::enumValue, "java.lang.String"); + checkCorrectException(check::incorrectAnnotationValue, "java.lang.Deprecated"); + checkCorrectException(check::incorrectArrayValue, ""); + checkCorrectException(check::incorrectClassValue, ""); + + seenGenerated = true; + } + + if (roundEnv.processingOver() && !seenGenerated) { + Assert.error("Did not see the generated class!"); + } + + return true; + } + + private static void checkCorrectException(Runnable runCheck, String expectedType) { + try { + runCheck.run(); + Assert.check(false); //Should not reach here + } catch (AnnotationTypeMismatchException ex) { + Assert.check(expectedType.equals(ex.foundType()), ex.foundType()); + } + } + +} + +@interface Gen { + String fileName(); + String content(); +} + +@interface Check { + Class classValue(); + int intConstValue(); + E enumValue(); + int incorrectAnnotationValue(); + int incorrectArrayValue(); + Class incorrectClassValue(); +} + +enum E { + A; +} diff -r 57913337d634 -r f3bec12a63e7 langtools/test/tools/javac/processing/errors/EnsureAnnotationTypeMismatchException/Source.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/processing/errors/EnsureAnnotationTypeMismatchException/Source.java Fri Oct 11 15:49:15 2013 +0200 @@ -0,0 +1,25 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6278240 + * @summary Ensure AnnotationTypeMismatchException is thrown when appropriate + * with reasonable foundType filled. + * @library /tools/javac/lib + * @build JavacTestingAbstractProcessor Processor + * @compile/fail/ref=Source.out -XDrawDiagnostics -processor Processor Source.java + */ + +@Gen(fileName="Generated", + content= +"class Generated {\n" + +" @Check(classValue=String.class,\n" + +" intConstValue=false,\n" + +" enumValue=\"a\",\n" + +" incorrectAnnotationValue=@Deprecated,\n" + +" incorrectArrayValue={1, \"a\"},\n" + +" incorrectClassValue=get())\n" + +" public static Class get() {\n" + +" return null;\n" + +" }\n" + +"}\n") +class Source { +} diff -r 57913337d634 -r f3bec12a63e7 langtools/test/tools/javac/processing/errors/EnsureAnnotationTypeMismatchException/Source.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/processing/errors/EnsureAnnotationTypeMismatchException/Source.out Fri Oct 11 15:49:15 2013 +0200 @@ -0,0 +1,7 @@ +Generated.java:2:29: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: java.lang.Class, java.lang.Class) +Generated.java:3:26: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: boolean, int) +Generated.java:4:22: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: java.lang.String, E) +Generated.java:5:37: compiler.err.annotation.not.valid.for.type: int +Generated.java:6:32: compiler.err.annotation.value.not.allowable.type +Generated.java:7:35: compiler.err.annotation.value.must.be.class.literal +6 errors