1/* 2 * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24/* 25 * @test 26 * @bug 8013852 8031744 27 * @summary Annotations on types 28 * @library /tools/javac/lib 29 * @modules jdk.compiler/com.sun.tools.javac.api 30 * jdk.compiler/com.sun.tools.javac.code 31 * jdk.compiler/com.sun.tools.javac.processing 32 * jdk.compiler/com.sun.tools.javac.tree 33 * jdk.compiler/com.sun.tools.javac.util 34 * @build JavacTestingAbstractProcessor DPrinter BasicAnnoTests 35 * @compile/process -XDaccessInternalAPI -processor BasicAnnoTests -proc:only BasicAnnoTests.java 36 */ 37 38import java.io.PrintWriter; 39import java.io.Serializable; 40import java.lang.annotation.Annotation; 41import java.lang.annotation.ElementType; 42import java.lang.annotation.Repeatable; 43import java.lang.annotation.Target; 44import java.util.ArrayList; 45 46import java.util.HashSet; 47import java.util.List; 48import java.util.Map; 49import java.util.NavigableMap; 50import java.util.Set; 51import java.util.TreeMap; 52 53import javax.annotation.processing.ProcessingEnvironment; 54import javax.annotation.processing.RoundEnvironment; 55import javax.lang.model.AnnotatedConstruct; 56import javax.lang.model.element.AnnotationMirror; 57import javax.lang.model.element.AnnotationValue; 58import javax.lang.model.element.Element; 59import javax.lang.model.element.ExecutableElement; 60import javax.lang.model.element.TypeElement; 61import javax.lang.model.type.ArrayType; 62import javax.lang.model.type.DeclaredType; 63import javax.lang.model.type.ExecutableType; 64import javax.lang.model.type.IntersectionType; 65import javax.lang.model.type.TypeMirror; 66import javax.lang.model.type.TypeVariable; 67import javax.lang.model.type.WildcardType; 68import javax.lang.model.util.Types; 69import javax.tools.Diagnostic.Kind; 70 71import com.sun.tools.javac.code.Attribute; 72import com.sun.tools.javac.code.Symbol; 73import com.sun.tools.javac.processing.JavacProcessingEnvironment; 74import com.sun.tools.javac.util.Name; 75 76import static com.sun.tools.javac.code.Attribute.Array; 77import static com.sun.tools.javac.code.Attribute.Constant; 78import static com.sun.tools.javac.code.Attribute.Compound; 79 80/** 81 * The test scans this file looking for test cases annotated with @Test. 82 */ 83public class BasicAnnoTests extends JavacTestingAbstractProcessor { 84 DPrinter dprinter; 85 PrintWriter out; 86 boolean verbose = true; 87 88 @Override 89 public void init(ProcessingEnvironment pEnv) { 90 super.init(pEnv); 91 dprinter = new DPrinter(((JavacProcessingEnvironment) pEnv).getContext()); 92 out = dprinter.out; 93 } 94 95 @Override 96 public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { 97 TestElementScanner s = new TestElementScanner(); 98 for (Element e: roundEnv.getRootElements()) { 99 s.scan(e, null); 100 } 101 return true; 102 } 103 104 void error(Element e, String msg) { 105 messager.printMessage(Kind.ERROR, msg, e); 106 errors++; 107 } 108 109 int errors; 110 111 /** 112 * Scan an element looking for declarations annotated with @Test. 113 * Run a TestTypeScanner on the annotations that are found. 114 */ 115 class TestElementScanner extends ElementScanner<Void,Void> { 116 public Void scan(Element elem, Void ignore) { 117 List<AnnotationMirror> tests = new ArrayList<>(); 118 AnnotationMirror test = getAnnotation(elem, Test.class.getName().replace('$', '.')); 119 if (test != null) { 120 tests.add(test); 121 } 122 tests.addAll(getAnnotations(elem, Tests.class.getName().replace('$', '.'))); 123 124 if (tests.size() > 0) { 125 out.println("Test: " + elem + " " + test); 126 TestTypeScanner s = new TestTypeScanner(elem, tests, types); 127 s.test(elem.asType()); 128 out.println(); 129 } 130 return super.scan(elem, ignore); 131 } 132 } 133 134 /** 135 * Scan the type of an element, looking for an annotation 136 * to match the expected annotation specified in the @Test annotation. 137 */ 138 class TestTypeScanner extends TypeScanner<Void, Void> { 139 Element elem; 140 NavigableMap<Integer, AnnotationMirror> toBeFound; 141 int count = 0; 142 Set<TypeMirror> seen = new HashSet<>(); 143 144 TestTypeScanner(Element elem, List<AnnotationMirror> tests, Types types) { 145 super(types); 146 this.elem = elem; 147 148 NavigableMap<Integer, AnnotationMirror> testByPos = new TreeMap<>(); 149 for (AnnotationMirror test : tests) { 150 for (int pos : getPosn(test)) { 151 testByPos.put(pos, test); 152 } 153 } 154 this.toBeFound = testByPos; 155 } 156 157 public void test(TypeMirror t) { 158 scan(t, null); 159 } 160 161 @Override 162 Void scan(TypeMirror t, Void ignore) { 163 if (t == null) 164 return DEFAULT_VALUE; 165 166 if (!seen.contains(t)) { 167 try { 168 seen.add(t); 169 if (verbose) 170 out.println("scan " + count + ": " + t); 171 if (toBeFound.size() > 0) { 172 if (toBeFound.firstKey().equals(count)) { 173 AnnotationMirror test = toBeFound.pollFirstEntry().getValue(); 174 String annoType = getAnnoType(test); 175 AnnotationMirror anno = getAnnotation(t, annoType); 176 if (anno == null) { 177 error(elem, "annotation not found on " + count + ": " + t); 178 } else { 179 String v = getValue(anno, "value").toString(); 180 if (v.equals(getExpect(test))) { 181 out.println("found " + anno + " as expected"); 182 } else { 183 error(elem, "Unexpected value: " + v + ", expected: " + getExpect(test)); 184 } 185 } 186 } else if (count > toBeFound.firstKey()) { 187 rescue(); 188 } else { 189 List<? extends AnnotationMirror> annos = t.getAnnotationMirrors(); 190 if (annos.size() > 0) { 191 for (AnnotationMirror a : annos) 192 error(elem, "annotation " + a + " found on " + count + ": " + t); 193 } 194 } 195 } else { 196 List<? extends AnnotationMirror> annos = t.getAnnotationMirrors(); 197 if (annos.size() > 0) { 198 for (AnnotationMirror a : annos) 199 error(elem, "annotation " + a + " found on " + count + ": " + t); 200 } 201 } 202 count++; 203 return super.scan(t, ignore); 204 205 } finally { 206 seen.remove(t); 207 } 208 } 209 210 return DEFAULT_VALUE; 211 212 } 213 214 private void rescue() { 215 while (toBeFound.size() > 0 && toBeFound.firstKey() >= count) 216 toBeFound.pollFirstEntry(); 217 } 218 } 219 220 /** Get the position value from an element annotated with a @Test annotation mirror. */ 221 static int[] getPosn(Element elem) { 222 return elem.getAnnotation(Test.class).posn(); 223 } 224 225 /** Get the position value from a @Test annotation mirror. */ 226 static Integer[] getPosn(AnnotationMirror test) { 227 AnnotationValue v = getValue(test, "posn"); 228 Object value = v.getValue(); 229 Integer i = 0; 230 if (value instanceof Constant) { 231 i = (Integer)((Constant)value).getValue(); 232 Integer[] res = new Integer[1]; 233 res[0] = i; 234 return res; 235 } else if (value instanceof List) { 236 List<Constant> l = (List<Constant>)value; 237 Integer[] res = new Integer[l.size()]; 238 for (int c = 0; c < l.size(); c++) { 239 res[c] = (Integer)l.get(c).getValue(); 240 } 241 return res; 242 } 243 return null; 244 } 245 246 /** Get the expect value from an @Test annotation mirror. */ 247 static String getExpect(AnnotationMirror test) { 248 AnnotationValue v = getValue(test, "expect"); 249 return (String) v.getValue(); 250 } 251 252 /** Get the annoType value from an @Test annotation mirror. */ 253 static String getAnnoType(AnnotationMirror test) { 254 AnnotationValue v = getValue(test, "annoType"); 255 TypeMirror m = (TypeMirror) v.getValue(); 256 return m.toString(); 257 } 258 259 /** 260 * Get a specific annotation mirror from an annotated construct. 261 */ 262 static AnnotationMirror getAnnotation(AnnotatedConstruct e, String name) { 263 for (AnnotationMirror m: e.getAnnotationMirrors()) { 264 TypeElement te = (TypeElement) m.getAnnotationType().asElement(); 265 if (te.getQualifiedName().contentEquals(name)) { 266 return m; 267 } 268 } 269 return null; 270 } 271 272 static List<AnnotationMirror> getAnnotations(Element e, String name) { 273 Name valueName = ((Symbol)e).getSimpleName().table.names.value; 274 List<AnnotationMirror> res = new ArrayList<>(); 275 276 for (AnnotationMirror m : e.getAnnotationMirrors()) { 277 TypeElement te = (TypeElement) m.getAnnotationType().asElement(); 278 if (te.getQualifiedName().contentEquals(name)) { 279 Compound theAnno = (Compound)m; 280 Array valueArray = (Array)theAnno.member(valueName); 281 for (Attribute a : valueArray.getValue()) { 282 AnnotationMirror theMirror = (AnnotationMirror) a; 283 284 res.add(theMirror); 285 } 286 } 287 } 288 return res; 289 } 290 291 /** 292 * Get a specific value from an annotation mirror. 293 */ 294 static AnnotationValue getValue(AnnotationMirror anno, String name) { 295 Map<? extends ExecutableElement, ? extends AnnotationValue> map = anno.getElementValues(); 296 for (Map.Entry<? extends ExecutableElement, ? extends AnnotationValue> e: map.entrySet()) { 297 if (e.getKey().getSimpleName().contentEquals(name)) { 298 return e.getValue(); 299 } 300 } 301 return null; 302 } 303 304 /** 305 * The Language Model API does not provide a type scanner, so provide 306 * one sufficient for our needs. 307 */ 308 static class TypeScanner<R, P> extends SimpleTypeVisitor<R, P> { 309 private Types types; 310 311 public TypeScanner(Types types) { 312 super(); 313 this.types = types; 314 } 315 316 @Override 317 public R visitArray(ArrayType t, P p) { 318 scan(t.getComponentType(), p); 319 return super.visitArray(t, p); 320 } 321 322 @Override 323 public R visitExecutable(ExecutableType t, P p) { 324 //out.println(" type parameters: " + t.getTypeVariables()); 325 scan(t.getTypeVariables(), p); 326 //out.println(" return: " + t.getReturnType()); 327 scan(t.getReturnType(), p); 328 //out.println(" receiver: " + t.getReceiverTypes()); 329 scan(t.getReceiverType()); 330 //out.println(" params: " + t.getParameterTypes()); 331 scan(t.getParameterTypes(), p); 332 //out.println(" throws: " + t.getThrownTypes()); 333 scan(t.getThrownTypes(), p); 334 return super.visitExecutable(t, p); 335 } 336 337 @Override 338 public R visitDeclared(DeclaredType t, P p) { 339 scan(t.getTypeArguments(), p); 340 // don't scan enclosing 341 scan(types.directSupertypes(t), p); 342 return super.visitDeclared(t, p); 343 } 344 345 @Override 346 public R visitIntersection(IntersectionType t, P p) { 347 scan(t.getBounds(), p); 348 return super.visitIntersection(t, p); 349 } 350 351 @Override 352 public R visitTypeVariable(TypeVariable t, P p) { 353 scan(t.getLowerBound(), p); 354 scan(t.getUpperBound(), p); 355 return super.visitTypeVariable(t, p); 356 } 357 358 @Override 359 public R visitWildcard(WildcardType t, P p) { 360 scan(t.getExtendsBound(), p); 361 scan(t.getSuperBound(), p); 362 return super.visitWildcard(t, p); 363 } 364 365 R scan(TypeMirror t) { 366 return scan(t, null); 367 } 368 369 R scan(TypeMirror t, P p) { 370 return (t == null) ? DEFAULT_VALUE : t.accept(this, p); 371 } 372 373 R scan(Iterable<? extends TypeMirror> iter, P p) { 374 if (iter == null) 375 return DEFAULT_VALUE; 376 R result = DEFAULT_VALUE; 377 for (TypeMirror t: iter) 378 result = scan(t, p); 379 return result; 380 } 381 } 382 383 /** Annotation to identify test cases. */ 384 @Repeatable(Tests.class) 385 @interface Test { 386 /** Where to look for the annotation, expressed as a scan index. */ 387 int[] posn(); 388 /** The annotation to look for. */ 389 Class<? extends Annotation> annoType(); 390 /** The string representation of the annotation's value. */ 391 String expect(); 392 } 393 394 @interface Tests { 395 Test[] value(); 396 } 397 398 /** Type annotation to use in test cases. */ 399 @Target(ElementType.TYPE_USE) 400 public @interface TA { 401 int value(); 402 } 403 @Target(ElementType.TYPE_USE) 404 public @interface TB { 405 int value(); 406 } 407 408 // Test cases 409 410 // TODO: add more cases for arrays 411 // all annotated 412 // all but one annotated 413 // vary position of one not annotated 414 // only one annotated 415 // vary position of one annotated 416 // the three above with the corner case of the ambiguos decl + type anno added 417 418 @Test(posn=0, annoType=TA.class, expect="1") 419 public @TA(1) int f1; 420 421 @Test(posn=0, annoType=TA.class, expect="11") 422 @TA(11) public int f11; 423 424 @Test(posn=1, annoType=TA.class, expect="111") 425 @TA(111) public int [] f111; 426 427 @Test(posn=1, annoType=TA.class, expect="1120") 428 @Test(posn=0, annoType=TB.class, expect="1121") 429 @TA(1120) public int @TB(1121) [] f112; 430 431 @Test(posn=0, annoType=TB.class, expect="11211") 432 @Test(posn=1, annoType=TA.class, expect="11200") 433 public @TA(11200) int @TB(11211) [] f112b; 434 435 @Test(posn=1, annoType=TB.class, expect="1131") 436 @Test(posn=2, annoType=TA.class, expect="1130") 437 @TA(1130) public int [] @TB(1131) [] f113; 438 439 @Test(posn=5, annoType=TA.class, expect="12") 440 public @TA(12) int [] [] [] [] [] f12; 441 442 @Test(posn=6, annoType=TA.class, expect="13") 443 public @TA(13) int [] [] [] [] [] [] f13; 444 445 @Test(posn=7, annoType=TA.class, expect="14") 446 @TA(14) public int [] [] [] [] [] [] [] f14; 447 448 @Test(posn=6, annoType=TA.class, expect="150") 449 @Test(posn=7, annoType=TB.class, expect="151") 450 @TB(151) public int [] [] [] [] [] [] @TA(150) [] f15; 451 452 @Test(posn=0, annoType=TB.class, expect="1511") 453 @Test(posn=3, annoType=TA.class, expect="1512") 454 @Test(posn=6, annoType=TA.class, expect="150") 455 @Test(posn=7, annoType=TB.class, expect="151") 456 @TB(151) public int @TB(1511) [] [] [] @TA(1512) [] [] [] @TA(150) [] f15b; 457 458 @Test(posn=0, annoType=TB.class, expect="1521") 459 @Test(posn=3, annoType=TA.class, expect="1522") 460 @Test(posn=6, annoType=TA.class, expect="152") 461 public int @TB(1521) [] [] [] @TA(1522) [] [] [] @TA(152) [] f15c; 462 463 @Test(posn=5, annoType=TA.class, expect="160") 464 @Test(posn=6, annoType=TB.class, expect="161") 465 public int [] [] [] [] [] @TA(160) [] @TB(161) [] f16; 466 467 @Test(posn=0, annoType=TA.class, expect="2") 468 public int @TA(2) [] f2; 469 470 @Test(posn=0, annoType=TB.class, expect="33") 471 @Test(posn=1, annoType=TA.class, expect="3") 472 public @TA(3) int @TB(33) [] f3; 473 474 @Test(posn=2, annoType=TA.class, expect="4") 475 public int m1(@TA(4) float a) throws Exception { return 0; } 476 477 @Test(posn=1, annoType=TA.class, expect="5") 478 public @TA(5) int m2(float a) throws Exception { return 0; } 479 480 @Test(posn=3, annoType=TA.class, expect="6") 481 public int m3(float a) throws @TA(6) Exception { return 0; } 482 483 // Also tests that a decl anno on a typevar doesn't show up on the Type 484 @Test(posn=7, annoType=TA.class, expect="8") 485 public <@TA(7) M> M m4(@TA(8) float a) throws Exception { return null; } 486 487 // Also tests that a decl anno on a typevar doesn't show up on the Type 488 @Test(posn=4, annoType=TA.class, expect="10") 489 public class Inner1<@TA(9) S> extends @TA(10) Object implements Cloneable {} 490 491 // Also tests that a decl anno on a typevar doesn't show up on the Type 492 @Test(posn=5, annoType=TA.class, expect="12") 493 public class Inner2<@TA(11) S> extends Object implements @TA(12) Cloneable {} 494 495 @Test(posn={3,6}, annoType=TA.class, expect="13") 496 public <M extends @TA(13) Object> M m5(float a) { return null; } 497 498 @Test(posn=3, annoType=TA.class, expect="14") 499 public class Inner3<QQQ extends @TA(14) Map> {} 500 501 @Test(posn=4, annoType=TA.class, expect="15") 502 public class Inner4<T extends @TA(15) Object & Cloneable & Serializable> {} 503 504 @Test(posn=5, annoType=TA.class, expect="16") 505 public class Inner5<T extends Object & @TA(16) Cloneable & Serializable> {} 506 507 @Test(posn=7, annoType=TA.class, expect="17") 508 public class Inner6<T extends Object & Cloneable & @TA(17) Serializable> {} 509 510 // Test annotated bounds 511 512 @Test(posn=1, annoType=TA.class, expect="18") 513 public Set<@TA(18) ? extends Object> f4; 514 515 @Test(posn=2, annoType=TA.class, expect="19") 516 public Set<? extends @TA(19) Object> f5; 517 518 @Test(posn=3, annoType=TA.class, expect="20") 519 public Set<? extends Set<@TA(20) ? extends Object>> f6; 520 521 @Test(posn=4, annoType=TA.class, expect="21") 522 public Set<? extends Set<? extends @TA(21) Object>> f7; 523 524 @Test(posn=1, annoType=TA.class, expect="22") 525 public Set<@TA(22) ?> f8; 526 527 @Test(posn=1, annoType=TA.class, expect="23") 528 public Set<@TA(23) ? super Object> f9; 529 530 // Test type use annotations on uses of type variables 531 @Test(posn=5, annoType = TA.class, expect = "25") 532 @Test(posn=5, annoType = TB.class, expect = "26") 533 <T> void m6(@TA(25) @TB(26) T t) { } 534 535 class Inner7<T> { 536 @Test(posn=0, annoType = TA.class, expect = "30") 537 @Test(posn=0, annoType = TB.class, expect = "31") 538 @TA(30) @TB(31) T f; 539 } 540 541 // Test type use annotations on uses of type variables 542 @Test(posn=5, annoType = TB.class, expect = "41") 543 <@TA(40) T> void m7(@TB(41) T t) { } 544 545 class Inner8<@TA(50) T> { 546 @Test(posn=0, annoType = TB.class, expect = "51") 547 @TB(51) T f; 548 } 549 550 // Test type use annotations on uses of Class types 551 @Test(posn=5, annoType = TA.class, expect = "60") 552 @Test(posn=5, annoType = TB.class, expect = "61") 553 <T> void m60(@TA(60) @TB(61) String t) { } 554 555 class Inner70<T> { 556 @Test(posn=0, annoType = TA.class, expect = "70") 557 @Test(posn=0, annoType = TB.class, expect = "71") 558 @TA(70) @TB(71) String f; 559 } 560 561 // Test type use annotations on uses of type variables 562 @Test(posn=5, annoType = TB.class, expect = "81") 563 <@TA(80) T> void m80(@TB(81) String t) { } 564 565 class Inner90<@TA(90) T> { 566 @Test(posn=0, annoType = TB.class, expect = "91") 567 @TB(91) String f; 568 } 569 570 // Recursive bound 571 @Test(posn=4, annoType = TB.class, expect = "100") 572 class Inner100<T extends Inner100<@TB(100) T>> { 573 } 574} 575