test/tools/javac/processing/model/type/BasicAnnoTests.java

Tue, 15 Oct 2013 15:57:13 -0700

author
jjg
date
Tue, 15 Oct 2013 15:57:13 -0700
changeset 2134
b0c086cd4520
parent 1755
ddb4a2bfcd82
child 2525
2eb010b6cb22
permissions
-rw-r--r--

8026564: import changes from type-annotations forest
Reviewed-by: jjg
Contributed-by: wdietl@gmail.com, steve.sides@oracle.com

jjg@1755 1 /*
jjg@1755 2 * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
jjg@1755 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
jjg@1755 4 *
jjg@1755 5 * This code is free software; you can redistribute it and/or modify it
jjg@1755 6 * under the terms of the GNU General Public License version 2 only, as
jjg@1755 7 * published by the Free Software Foundation.
jjg@1755 8 *
jjg@1755 9 * This code is distributed in the hope that it will be useful, but WITHOUT
jjg@1755 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
jjg@1755 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
jjg@1755 12 * version 2 for more details (a copy is included in the LICENSE file that
jjg@1755 13 * accompanied this code).
jjg@1755 14 *
jjg@1755 15 * You should have received a copy of the GNU General Public License version
jjg@1755 16 * 2 along with this work; if not, write to the Free Software Foundation,
jjg@1755 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
jjg@1755 18 *
jjg@1755 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
jjg@1755 20 * or visit www.oracle.com if you need additional information or have any
jjg@1755 21 * questions.
jjg@1755 22 */
jjg@1755 23
jjg@1755 24 /*
jjg@1755 25 * @test
jjg@1755 26 * @bug 1234567
jjg@1755 27 * @summary Annotations on types
jjg@1755 28 * @library /tools/javac/lib
jjg@2134 29 * @ignore
jjg@1755 30 * @build JavacTestingAbstractProcessor DPrinter BasicAnnoTests
jjg@1755 31 * @compile/process -processor BasicAnnoTests -proc:only BasicAnnoTests.java
jjg@1755 32 */
jjg@1755 33
jjg@1755 34 import java.io.PrintWriter;
jjg@1755 35 import java.lang.annotation.Annotation;
jjg@1755 36 import java.lang.annotation.ElementType;
jjg@1755 37 import java.lang.annotation.Target;
jjg@1755 38 import java.util.Map;
jjg@1755 39 import java.util.Set;
jjg@1755 40
jjg@1755 41 import javax.annotation.processing.ProcessingEnvironment;
jjg@1755 42 import javax.annotation.processing.RoundEnvironment;
jjg@1755 43 import javax.lang.model.AnnotatedConstruct;
jjg@1755 44 import javax.lang.model.element.AnnotationMirror;
jjg@1755 45 import javax.lang.model.element.AnnotationValue;
jjg@1755 46 import javax.lang.model.element.Element;
jjg@1755 47 import javax.lang.model.element.ExecutableElement;
jjg@1755 48 import javax.lang.model.element.TypeElement;
jjg@1755 49 import javax.lang.model.type.ArrayType;
jjg@1755 50 import javax.lang.model.type.ExecutableType;
jjg@1755 51 import javax.lang.model.type.TypeMirror;
jjg@1755 52 import javax.lang.model.type.TypeVariable;
jjg@1755 53 import javax.lang.model.type.WildcardType;
jjg@1755 54 import javax.tools.Diagnostic.Kind;
jjg@1755 55
jjg@1755 56 import com.sun.tools.javac.code.Symbol;
jjg@1755 57 import com.sun.tools.javac.code.Type;
jjg@1755 58 import com.sun.tools.javac.processing.JavacProcessingEnvironment;
jjg@1755 59
jjg@1755 60 /**
jjg@1755 61 * The test scans this file looking for test cases annotated with @Test.
jjg@1755 62 */
jjg@1755 63 public class BasicAnnoTests extends JavacTestingAbstractProcessor {
jjg@1755 64 DPrinter dprinter;
jjg@1755 65 PrintWriter out;
jjg@1755 66 boolean verbose = true;
jjg@1755 67
jjg@1755 68 @Override
jjg@1755 69 public void init(ProcessingEnvironment pEnv) {
jjg@1755 70 super.init(pEnv);
jjg@1755 71 dprinter = new DPrinter(((JavacProcessingEnvironment) pEnv).getContext());
jjg@1755 72 out = dprinter.out;
jjg@1755 73 }
jjg@1755 74
jjg@1755 75 @Override
jjg@1755 76 public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
jjg@1755 77 TestElementScanner s = new TestElementScanner();
jjg@1755 78 for (Element e: roundEnv.getRootElements()) {
jjg@1755 79 s.scan(e);
jjg@1755 80 }
jjg@1755 81 return true;
jjg@1755 82 }
jjg@1755 83
jjg@1755 84 void error(Element e, String msg) {
jjg@1755 85 messager.printMessage(Kind.ERROR, msg, e);
jjg@1755 86 errors++;
jjg@1755 87 }
jjg@1755 88
jjg@1755 89 int errors;
jjg@1755 90
jjg@1755 91 /**
jjg@1755 92 * Scan an element looking for declarations annotated with @Test.
jjg@1755 93 * Run a TestTypeScanner on the annotations that are found.
jjg@1755 94 */
jjg@1755 95 class TestElementScanner extends ElementScanner<Void,Void> {
jjg@1755 96 public Void scan(Element elem, Void ignore) {
jjg@1755 97 AnnotationMirror test = getAnnotation(elem, Test.class.getName().replace('$', '.'));
jjg@1755 98 if (test != null) {
jjg@1755 99 out.println("Test: " + elem + " " + test);
jjg@1755 100 TestTypeScanner s = new TestTypeScanner(elem, test);
jjg@1755 101 s.scan(elem.asType(), null);
jjg@1755 102 if (getPosn(test) >= s.count)
jjg@1755 103 error(elem, "position " + getPosn(test) + " not found");
jjg@1755 104 if (!s.found) {
jjg@1755 105 dprinter.printSymbol("element", (Symbol) elem);
jjg@1755 106 dprinter.printType("type", (Type) elem.asType());
jjg@1755 107 }
jjg@1755 108 out.println();
jjg@1755 109 }
jjg@1755 110 return super.scan(elem, ignore);
jjg@1755 111 }
jjg@1755 112 }
jjg@1755 113
jjg@1755 114 /**
jjg@1755 115 * Scan the type of an element, looking for an annotation
jjg@1755 116 * to match the expected annotation specified in the @Test annotation.
jjg@1755 117 */
jjg@1755 118 class TestTypeScanner extends TypeScanner<Void, Void> {
jjg@1755 119 Element elem;
jjg@1755 120 AnnotationMirror test;
jjg@1755 121 int count = 0;
jjg@1755 122 boolean found = false;
jjg@1755 123
jjg@1755 124 TestTypeScanner(Element elem, AnnotationMirror test) {
jjg@1755 125 this.elem = elem;
jjg@1755 126 this.test = test;
jjg@1755 127 }
jjg@1755 128
jjg@1755 129 @Override
jjg@1755 130 Void scan(TypeMirror t, Void ignore) {
jjg@1755 131 if (t == null)
jjg@1755 132 return DEFAULT_VALUE;
jjg@1755 133 if (verbose)
jjg@1755 134 out.println("scan " + count + ": " + t);
jjg@1755 135 if (count == getPosn(test)) {
jjg@1755 136 String annoType = getAnnoType(test);
jjg@1755 137 AnnotationMirror anno = getAnnotation(t, annoType);
jjg@1755 138 if (anno == null) {
jjg@1755 139 error(elem, "annotation not found on " + count + ": " + t);
jjg@1755 140 } else {
jjg@1755 141 String v = getValue(anno, "value").toString();
jjg@1755 142 if (v.equals(getExpect(test))) {
jjg@1755 143 out.println("found " + anno + " as expected");
jjg@1755 144 found = true;
jjg@1755 145 } else {
jjg@1755 146 error(elem, "Unexpected value: " + v + ", expected: " + getExpect(test));
jjg@1755 147 }
jjg@1755 148 }
jjg@1755 149 }
jjg@1755 150 count++;
jjg@1755 151 return super.scan(t, ignore);
jjg@1755 152 }
jjg@1755 153 }
jjg@1755 154
jjg@1755 155 /** Get the position value from an @Test annotation mirror. */
jjg@1755 156 static int getPosn(AnnotationMirror test) {
jjg@1755 157 AnnotationValue v = getValue(test, "posn");
jjg@1755 158 return (Integer) v.getValue();
jjg@1755 159 }
jjg@1755 160
jjg@1755 161 /** Get the expect value from an @Test annotation mirror. */
jjg@1755 162 static String getExpect(AnnotationMirror test) {
jjg@1755 163 AnnotationValue v = getValue(test, "expect");
jjg@1755 164 return (String) v.getValue();
jjg@1755 165 }
jjg@1755 166
jjg@1755 167 /** Get the annoType value from an @Test annotation mirror. */
jjg@1755 168 static String getAnnoType(AnnotationMirror test) {
jjg@1755 169 AnnotationValue v = getValue(test, "annoType");
jjg@1755 170 TypeMirror m = (TypeMirror) v.getValue();
jjg@1755 171 return m.toString();
jjg@1755 172 }
jjg@1755 173
jjg@1755 174 /**
jjg@1755 175 * Get a specific annotation mirror from an annotated construct.
jjg@1755 176 */
jjg@1755 177 static AnnotationMirror getAnnotation(AnnotatedConstruct e, String name) {
jjg@1755 178 for (AnnotationMirror m: e.getAnnotationMirrors()) {
jjg@1755 179 TypeElement te = (TypeElement) m.getAnnotationType().asElement();
jjg@1755 180 if (te.getQualifiedName().contentEquals(name)) {
jjg@1755 181 return m;
jjg@1755 182 }
jjg@1755 183 }
jjg@1755 184 return null;
jjg@1755 185 }
jjg@1755 186
jjg@1755 187 /**
jjg@1755 188 * Get a specific value from an annotation mirror.
jjg@1755 189 */
jjg@1755 190 static AnnotationValue getValue(AnnotationMirror anno, String name) {
jjg@1755 191 Map<? extends ExecutableElement, ? extends AnnotationValue> map = anno.getElementValues();
jjg@1755 192 for (Map.Entry<? extends ExecutableElement, ? extends AnnotationValue> e: map.entrySet()) {
jjg@1755 193 if (e.getKey().getSimpleName().contentEquals(name)) {
jjg@1755 194 return e.getValue();
jjg@1755 195 }
jjg@1755 196 }
jjg@1755 197 return null;
jjg@1755 198 }
jjg@1755 199
jjg@1755 200 /**
jjg@1755 201 * The Language Model API does not provide a type scanner, so provide
jjg@1755 202 * one sufficient for our needs.
jjg@1755 203 */
jjg@1755 204 static class TypeScanner<R, P> extends SimpleTypeVisitor<R, P> {
jjg@1755 205 @Override
jjg@1755 206 public R visitArray(ArrayType t, P p) {
jjg@1755 207 scan(t.getComponentType(), p);
jjg@1755 208 return super.visitArray(t, p);
jjg@1755 209 }
jjg@1755 210
jjg@1755 211 @Override
jjg@1755 212 public R visitExecutable(ExecutableType t, P p) {
jjg@1755 213 scan(t.getReceiverType());
jjg@1755 214 //out.println(" params: " + t.getParameterTypes());
jjg@1755 215 scan(t.getParameterTypes(), p);
jjg@1755 216 //out.println(" return: " + t.getReturnType());
jjg@1755 217 scan(t.getReturnType(), p);
jjg@1755 218 //out.println(" throws: " + t.getThrownTypes());
jjg@1755 219 scan(t.getThrownTypes(), p);
jjg@1755 220 return super.visitExecutable(t, p);
jjg@1755 221 }
jjg@1755 222
jjg@1755 223 @Override
jjg@1755 224 public R visitTypeVariable(TypeVariable t, P p) {
jjg@1755 225 scan(t.getLowerBound(), p);
jjg@1755 226 scan(t.getUpperBound(), p);
jjg@1755 227 return super.visitTypeVariable(t, p);
jjg@1755 228 }
jjg@1755 229
jjg@1755 230 @Override
jjg@1755 231 public R visitWildcard(WildcardType t, P p) {
jjg@1755 232 scan(t.getExtendsBound(), p);
jjg@1755 233 scan(t.getSuperBound(), p);
jjg@1755 234 return super.visitWildcard(t, p);
jjg@1755 235 }
jjg@1755 236
jjg@1755 237 R scan(TypeMirror t) {
jjg@1755 238 return scan(t, null);
jjg@1755 239 }
jjg@1755 240
jjg@1755 241 R scan(TypeMirror t, P p) {
jjg@1755 242 return (t == null) ? DEFAULT_VALUE : t.accept(this, p);
jjg@1755 243 }
jjg@1755 244
jjg@1755 245 R scan(Iterable<? extends TypeMirror> iter, P p) {
jjg@1755 246 if (iter == null)
jjg@1755 247 return DEFAULT_VALUE;
jjg@1755 248 R result = DEFAULT_VALUE;
jjg@1755 249 for (TypeMirror t: iter)
jjg@1755 250 result = scan(t, p);
jjg@1755 251 return result;
jjg@1755 252 }
jjg@1755 253 }
jjg@1755 254
jjg@1755 255 /** Annotation to identify test cases. */
jjg@1755 256 @interface Test {
jjg@1755 257 /** Where to look for the annotation, expressed as a scan index. */
jjg@1755 258 int posn();
jjg@1755 259 /** The annotation to look for. */
jjg@1755 260 Class<? extends Annotation> annoType();
jjg@1755 261 /** The string representation of the annotation's value. */
jjg@1755 262 String expect();
jjg@1755 263 }
jjg@1755 264
jjg@1755 265 /** Type annotation to use in test cases. */
jjg@1755 266 @Target(ElementType.TYPE_USE)
jjg@1755 267 public @interface TA {
jjg@1755 268 int value();
jjg@1755 269 }
jjg@1755 270
jjg@1755 271 @Test(posn=0, annoType=TA.class, expect="1")
jjg@1755 272 public @TA(1) int f1;
jjg@1755 273
jjg@1755 274 @Test(posn=0, annoType=TA.class, expect="2")
jjg@1755 275 public int @TA(2) [] f2;
jjg@1755 276
jjg@1755 277 @Test(posn=1, annoType=TA.class, expect="3")
jjg@1755 278 public @TA(3) int [] f3;
jjg@1755 279
jjg@1755 280 @Test(posn=1, annoType=TA.class, expect="4")
jjg@1755 281 public int m1(@TA(4) float a) throws Exception { return 0; }
jjg@1755 282
jjg@1755 283 @Test(posn=2, annoType=TA.class, expect="5")
jjg@1755 284 public @TA(5) int m2(float a) throws Exception { return 0; }
jjg@1755 285
jjg@1755 286 @Test(posn=3, annoType=TA.class, expect="6")
jjg@1755 287 public int m3(float a) throws @TA(6) Exception { return 0; }
jjg@1755 288 }

mercurial