test/tools/javac/tree/TreePosRoundsTest.java

Tue, 28 Dec 2010 15:54:52 -0800

author
ohair
date
Tue, 28 Dec 2010 15:54:52 -0800
changeset 798
4868a36f6fd8
parent 696
d4df3b6ee729
child 2525
2eb010b6cb22
permissions
-rw-r--r--

6962318: Update copyright year
Reviewed-by: xdono

     1 /*
     2  * Copyright (c) 2010, 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 6985205 6986246
    27  * @summary access to tree positions and doc comments may be lost across annotation processing rounds
    28  * @build TreePosRoundsTest
    29  * @compile -proc:only -processor TreePosRoundsTest TreePosRoundsTest.java
    30  * @run main TreePosRoundsTest
    31  */
    33 import java.io.*;
    34 import java.util.*;
    35 import javax.annotation.processing.*;
    36 import javax.lang.model.*;
    37 import javax.lang.model.element.*;
    38 import javax.tools.*;
    40 import com.sun.source.tree.*;
    41 import com.sun.source.util.*;
    42 import javax.tools.JavaCompiler.CompilationTask;
    44 // This test is an annotation processor that performs multiple rounds of
    45 // processing, and on each round, it checks that source positions are
    46 // available and correct.
    47 //
    48 // The test can be run directly as a processor from the javac command line
    49 // or via JSR 199 by invoking the main program.
    51 @SupportedAnnotationTypes("*")
    52 public class TreePosRoundsTest extends AbstractProcessor {
    53     public static void main(String... args) throws Exception {
    54         String testSrc = System.getProperty("test.src");
    55         String testClasses = System.getProperty("test.classes");
    56         JavaCompiler c = ToolProvider.getSystemJavaCompiler();
    57         StandardJavaFileManager fm = c.getStandardFileManager(null, null, null);
    58         String thisName = TreePosRoundsTest.class.getName();
    59         File thisFile = new File(testSrc, thisName + ".java");
    60         Iterable<? extends JavaFileObject> files = fm.getJavaFileObjects(thisFile);
    61         List<String> options = Arrays.asList(
    62                 "-proc:only",
    63                 "-processor", thisName,
    64                 "-processorpath", testClasses);
    65         CompilationTask t = c.getTask(null, fm, null, options, null, files);
    66         boolean ok = t.call();
    67         if (!ok)
    68             throw new Exception("processing failed");
    69     }
    71     Filer filer;
    72     Messager messager;
    73     Trees trees;
    75     @Override
    76     public SourceVersion getSupportedSourceVersion() {
    77         return SourceVersion.latest();
    78     }
    80     @Override
    81     public void init(ProcessingEnvironment pEnv) {
    82         super.init(pEnv);
    83         filer = pEnv.getFiler();
    84         messager = pEnv.getMessager();
    85         trees = Trees.instance(pEnv);
    86     }
    88     int round = 0;
    90     @Override
    91     public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
    92         round++;
    94         // Scan trees for elements, verifying source tree positions
    95         for (Element e: roundEnv.getRootElements()) {
    96             try {
    97                 TreePath p = trees.getPath(e);
    98                 new TestTreeScanner(p.getCompilationUnit(), trees).scan(trees.getPath(e), null);
    99             } catch (IOException ex) {
   100                 messager.printMessage(Diagnostic.Kind.ERROR,
   101                         "Cannot get source: " + ex, e);
   102             }
   103         }
   105         final int MAXROUNDS = 3;
   106         if (round < MAXROUNDS)
   107             generateSource("Gen" + round);
   109         return true;
   110     }
   112     void generateSource(String name) {
   113         StringBuilder text = new StringBuilder();
   114         text.append("class ").append(name).append("{\n");
   115         text.append("    int one = 1;\n");
   116         text.append("    int two = 2;\n");
   117         text.append("    int three = one + two;\n");
   118         text.append("}\n");
   120         try {
   121             JavaFileObject fo = filer.createSourceFile(name);
   122             Writer out = fo.openWriter();
   123             try {
   124                 out.write(text.toString());
   125             } finally {
   126                 out.close();
   127             }
   128         } catch (IOException e) {
   129             throw new Error(e);
   130         }
   131     }
   133     class TestTreeScanner extends TreePathScanner<Void,Void> {
   134         TestTreeScanner(CompilationUnitTree unit, Trees trees) throws IOException {
   135             this.unit = unit;
   136             JavaFileObject sf = unit.getSourceFile();
   137             source = sf.getCharContent(true).toString();
   138             sourcePositions = trees.getSourcePositions();
   139         }
   141         @Override
   142         public Void visitVariable(VariableTree tree, Void _) {
   143             check(getCurrentPath());
   144             return super.visitVariable(tree, _);
   145         }
   147         void check(TreePath tp) {
   148             Tree tree = tp.getLeaf();
   150             String expect = tree.toString();
   151             if (tree.getKind() == Tree.Kind.VARIABLE) {
   152                 // tree.toString() does not know enough context to add ";",
   153                 // so deal with that manually...
   154                 Tree.Kind enclKind = tp.getParentPath().getLeaf().getKind();
   155                 //System.err.println("  encl: " +enclKind);
   156                 if (enclKind == Tree.Kind.CLASS || enclKind == Tree.Kind.BLOCK)
   157                     expect += ";";
   158             }
   159             //System.err.println("expect: " + expect);
   161             int start = (int)sourcePositions.getStartPosition(unit, tree);
   162             if (start == Diagnostic.NOPOS) {
   163                 messager.printMessage(Diagnostic.Kind.ERROR, "start pos not set for " + trim(tree));
   164                 return;
   165             }
   167             int end = (int)sourcePositions.getEndPosition(unit, tree);
   168             if (end == Diagnostic.NOPOS) {
   169                 messager.printMessage(Diagnostic.Kind.ERROR, "end pos not set for " + trim(tree));
   170                 return;
   171             }
   173             String found = source.substring(start, end);
   174             //System.err.println(" found: " + found);
   176             // allow for long lines, in which case just compare beginning and
   177             // end of the strings
   178             boolean equal;
   179             if (found.contains("\n")) {
   180                 String head = found.substring(0, found.indexOf("\n"));
   181                 String tail = found.substring(found.lastIndexOf("\n")).trim();
   182                 equal = expect.startsWith(head) && expect.endsWith(tail);
   183             } else {
   184                 equal = expect.equals(found);
   185             }
   187             if (!equal) {
   188                 messager.printMessage(Diagnostic.Kind.ERROR,
   189                         "unexpected value found: '" + found + "'; expected: '" + expect + "'");
   190             }
   191         }
   193         String trim(Tree tree) {
   194             final int MAXLEN = 32;
   195             String s = tree.toString().replaceAll("\\s+", " ").trim();
   196             return (s.length() < MAXLEN) ? s : s.substring(0, MAXLEN);
   198         }
   200         CompilationUnitTree unit;
   201         SourcePositions sourcePositions;
   202         String source;
   203     }
   205 }

mercurial