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

     1 /*
     2  * Copyright (c) 2013, 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  */
    24 /*
    25  * @test
    26  * @bug     1234567
    27  * @summary Annotations on types
    28  * @library /tools/javac/lib
    29  * @ignore
    30  * @build JavacTestingAbstractProcessor DPrinter BasicAnnoTests
    31  * @compile/process -processor BasicAnnoTests -proc:only BasicAnnoTests.java
    32  */
    34 import java.io.PrintWriter;
    35 import java.lang.annotation.Annotation;
    36 import java.lang.annotation.ElementType;
    37 import java.lang.annotation.Target;
    38 import java.util.Map;
    39 import java.util.Set;
    41 import javax.annotation.processing.ProcessingEnvironment;
    42 import javax.annotation.processing.RoundEnvironment;
    43 import javax.lang.model.AnnotatedConstruct;
    44 import javax.lang.model.element.AnnotationMirror;
    45 import javax.lang.model.element.AnnotationValue;
    46 import javax.lang.model.element.Element;
    47 import javax.lang.model.element.ExecutableElement;
    48 import javax.lang.model.element.TypeElement;
    49 import javax.lang.model.type.ArrayType;
    50 import javax.lang.model.type.ExecutableType;
    51 import javax.lang.model.type.TypeMirror;
    52 import javax.lang.model.type.TypeVariable;
    53 import javax.lang.model.type.WildcardType;
    54 import javax.tools.Diagnostic.Kind;
    56 import com.sun.tools.javac.code.Symbol;
    57 import com.sun.tools.javac.code.Type;
    58 import com.sun.tools.javac.processing.JavacProcessingEnvironment;
    60 /**
    61  * The test scans this file looking for test cases annotated with @Test.
    62  */
    63 public class BasicAnnoTests extends JavacTestingAbstractProcessor {
    64     DPrinter dprinter;
    65     PrintWriter out;
    66     boolean verbose = true;
    68     @Override
    69     public void init(ProcessingEnvironment pEnv) {
    70         super.init(pEnv);
    71         dprinter = new DPrinter(((JavacProcessingEnvironment) pEnv).getContext());
    72         out = dprinter.out;
    73     }
    75     @Override
    76     public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
    77         TestElementScanner s = new TestElementScanner();
    78         for (Element e: roundEnv.getRootElements()) {
    79             s.scan(e);
    80         }
    81         return true;
    82     }
    84     void error(Element e, String msg) {
    85         messager.printMessage(Kind.ERROR, msg, e);
    86         errors++;
    87     }
    89     int errors;
    91     /**
    92      * Scan an element looking for declarations annotated with @Test.
    93      * Run a TestTypeScanner on the annotations that are found.
    94      */
    95     class TestElementScanner extends ElementScanner<Void,Void> {
    96         public Void scan(Element elem, Void ignore) {
    97             AnnotationMirror test = getAnnotation(elem, Test.class.getName().replace('$', '.'));
    98             if (test != null) {
    99                 out.println("Test: " + elem + " " + test);
   100                 TestTypeScanner s = new TestTypeScanner(elem, test);
   101                 s.scan(elem.asType(), null);
   102                 if (getPosn(test) >= s.count)
   103                     error(elem, "position " + getPosn(test) + " not found");
   104                 if (!s.found) {
   105                     dprinter.printSymbol("element", (Symbol) elem);
   106                     dprinter.printType("type", (Type) elem.asType());
   107                 }
   108                 out.println();
   109             }
   110             return super.scan(elem, ignore);
   111         }
   112     }
   114     /**
   115      * Scan the type of an element, looking for an annotation
   116      * to match the expected annotation specified in the @Test annotation.
   117      */
   118     class TestTypeScanner extends TypeScanner<Void, Void> {
   119         Element elem;
   120         AnnotationMirror test;
   121         int count = 0;
   122         boolean found = false;
   124         TestTypeScanner(Element elem, AnnotationMirror test) {
   125             this.elem = elem;
   126             this.test = test;
   127         }
   129         @Override
   130         Void scan(TypeMirror t, Void ignore) {
   131             if (t == null)
   132                 return DEFAULT_VALUE;
   133             if (verbose)
   134                 out.println("scan " + count + ": " + t);
   135             if (count == getPosn(test)) {
   136                 String annoType = getAnnoType(test);
   137                 AnnotationMirror anno = getAnnotation(t, annoType);
   138                 if (anno == null) {
   139                     error(elem, "annotation not found on " + count + ": " + t);
   140                 } else {
   141                     String v = getValue(anno, "value").toString();
   142                     if (v.equals(getExpect(test))) {
   143                         out.println("found " + anno + " as expected");
   144                         found = true;
   145                     } else {
   146                         error(elem, "Unexpected value: " + v + ", expected: " + getExpect(test));
   147                     }
   148                 }
   149             }
   150             count++;
   151             return super.scan(t, ignore);
   152         }
   153     }
   155     /** Get the position value from an @Test annotation mirror. */
   156     static int getPosn(AnnotationMirror test) {
   157         AnnotationValue v = getValue(test, "posn");
   158         return (Integer) v.getValue();
   159     }
   161     /** Get the expect value from an @Test annotation mirror. */
   162     static String getExpect(AnnotationMirror test) {
   163         AnnotationValue v = getValue(test, "expect");
   164         return (String) v.getValue();
   165     }
   167     /** Get the annoType value from an @Test annotation mirror. */
   168     static String getAnnoType(AnnotationMirror test) {
   169         AnnotationValue v = getValue(test, "annoType");
   170         TypeMirror m = (TypeMirror) v.getValue();
   171         return m.toString();
   172     }
   174     /**
   175      * Get a specific annotation mirror from an annotated construct.
   176      */
   177     static AnnotationMirror getAnnotation(AnnotatedConstruct e, String name) {
   178         for (AnnotationMirror m: e.getAnnotationMirrors()) {
   179             TypeElement te = (TypeElement) m.getAnnotationType().asElement();
   180             if (te.getQualifiedName().contentEquals(name)) {
   181                 return m;
   182             }
   183         }
   184         return null;
   185     }
   187     /**
   188      * Get a specific value from an annotation mirror.
   189      */
   190     static AnnotationValue getValue(AnnotationMirror anno, String name) {
   191         Map<? extends ExecutableElement, ? extends AnnotationValue> map = anno.getElementValues();
   192         for (Map.Entry<? extends ExecutableElement, ? extends AnnotationValue> e: map.entrySet()) {
   193             if (e.getKey().getSimpleName().contentEquals(name)) {
   194                 return e.getValue();
   195             }
   196         }
   197         return null;
   198     }
   200     /**
   201      * The Language Model API does not provide a type scanner, so provide
   202      * one sufficient for our needs.
   203      */
   204     static class TypeScanner<R, P> extends SimpleTypeVisitor<R, P> {
   205         @Override
   206         public R visitArray(ArrayType t, P p) {
   207             scan(t.getComponentType(), p);
   208             return super.visitArray(t, p);
   209         }
   211         @Override
   212         public R visitExecutable(ExecutableType t, P p) {
   213             scan(t.getReceiverType());
   214             //out.println("  params: " + t.getParameterTypes());
   215             scan(t.getParameterTypes(), p);
   216             //out.println("  return: " + t.getReturnType());
   217             scan(t.getReturnType(), p);
   218             //out.println("  throws: " + t.getThrownTypes());
   219             scan(t.getThrownTypes(), p);
   220             return super.visitExecutable(t, p);
   221         }
   223         @Override
   224         public R visitTypeVariable(TypeVariable t, P p) {
   225             scan(t.getLowerBound(), p);
   226             scan(t.getUpperBound(), p);
   227             return super.visitTypeVariable(t, p);
   228         }
   230         @Override
   231         public R visitWildcard(WildcardType t, P p) {
   232             scan(t.getExtendsBound(), p);
   233             scan(t.getSuperBound(), p);
   234             return super.visitWildcard(t, p);
   235         }
   237         R scan(TypeMirror t) {
   238             return scan(t, null);
   239         }
   241         R scan(TypeMirror t, P p) {
   242             return (t == null) ? DEFAULT_VALUE : t.accept(this, p);
   243         }
   245         R scan(Iterable<? extends TypeMirror> iter, P p) {
   246             if (iter == null)
   247                 return DEFAULT_VALUE;
   248             R result = DEFAULT_VALUE;
   249             for (TypeMirror t: iter)
   250                 result = scan(t, p);
   251             return result;
   252         }
   253     }
   255     /** Annotation to identify test cases. */
   256     @interface Test {
   257         /** Where to look for the annotation, expressed as a scan index. */
   258         int posn();
   259         /** The annotation to look for. */
   260         Class<? extends Annotation> annoType();
   261         /** The string representation of the annotation's value. */
   262         String expect();
   263     }
   265     /** Type annotation to use in test cases. */
   266     @Target(ElementType.TYPE_USE)
   267     public @interface TA {
   268         int value();
   269     }
   271     @Test(posn=0, annoType=TA.class, expect="1")
   272     public @TA(1) int f1;
   274     @Test(posn=0, annoType=TA.class, expect="2")
   275     public int @TA(2) [] f2;
   277     @Test(posn=1, annoType=TA.class, expect="3")
   278     public @TA(3) int [] f3;
   280     @Test(posn=1, annoType=TA.class, expect="4")
   281     public int m1(@TA(4) float a) throws Exception { return 0; }
   283     @Test(posn=2, annoType=TA.class, expect="5")
   284     public @TA(5) int m2(float a) throws Exception { return 0; }
   286     @Test(posn=3, annoType=TA.class, expect="6")
   287     public int m3(float a) throws @TA(6) Exception { return 0; }
   288 }

mercurial