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

jjg@695 1 /*
jjg@695 2 * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
jjg@695 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
jjg@695 4 *
jjg@695 5 * This code is free software; you can redistribute it and/or modify it
jjg@695 6 * under the terms of the GNU General Public License version 2 only, as
jjg@695 7 * published by the Free Software Foundation.
jjg@695 8 *
jjg@695 9 * This code is distributed in the hope that it will be useful, but WITHOUT
jjg@695 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
jjg@695 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
jjg@695 12 * version 2 for more details (a copy is included in the LICENSE file that
jjg@695 13 * accompanied this code).
jjg@695 14 *
jjg@695 15 * You should have received a copy of the GNU General Public License version
jjg@695 16 * 2 along with this work; if not, write to the Free Software Foundation,
jjg@695 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
jjg@695 18 *
jjg@695 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
jjg@695 20 * or visit www.oracle.com if you need additional information or have any
jjg@695 21 * questions.
jjg@695 22 */
jjg@695 23
jjg@695 24 /*
jjg@695 25 * @test
jjg@696 26 * @bug 6985205 6986246
jjg@695 27 * @summary access to tree positions and doc comments may be lost across annotation processing rounds
jjg@695 28 * @build TreePosRoundsTest
jjg@695 29 * @compile -proc:only -processor TreePosRoundsTest TreePosRoundsTest.java
jjg@695 30 * @run main TreePosRoundsTest
jjg@695 31 */
jjg@695 32
jjg@695 33 import java.io.*;
jjg@695 34 import java.util.*;
jjg@695 35 import javax.annotation.processing.*;
jjg@695 36 import javax.lang.model.*;
jjg@695 37 import javax.lang.model.element.*;
jjg@695 38 import javax.tools.*;
jjg@695 39
jjg@695 40 import com.sun.source.tree.*;
jjg@695 41 import com.sun.source.util.*;
jjg@695 42 import javax.tools.JavaCompiler.CompilationTask;
jjg@695 43
jjg@695 44 // This test is an annotation processor that performs multiple rounds of
jjg@695 45 // processing, and on each round, it checks that source positions are
jjg@695 46 // available and correct.
jjg@695 47 //
jjg@695 48 // The test can be run directly as a processor from the javac command line
jjg@695 49 // or via JSR 199 by invoking the main program.
jjg@695 50
jjg@695 51 @SupportedAnnotationTypes("*")
jjg@695 52 public class TreePosRoundsTest extends AbstractProcessor {
jjg@695 53 public static void main(String... args) throws Exception {
jjg@695 54 String testSrc = System.getProperty("test.src");
jjg@695 55 String testClasses = System.getProperty("test.classes");
jjg@695 56 JavaCompiler c = ToolProvider.getSystemJavaCompiler();
jjg@695 57 StandardJavaFileManager fm = c.getStandardFileManager(null, null, null);
jjg@695 58 String thisName = TreePosRoundsTest.class.getName();
jjg@695 59 File thisFile = new File(testSrc, thisName + ".java");
jjg@695 60 Iterable<? extends JavaFileObject> files = fm.getJavaFileObjects(thisFile);
jjg@695 61 List<String> options = Arrays.asList(
jjg@695 62 "-proc:only",
jjg@695 63 "-processor", thisName,
jjg@695 64 "-processorpath", testClasses);
jjg@695 65 CompilationTask t = c.getTask(null, fm, null, options, null, files);
jjg@695 66 boolean ok = t.call();
jjg@695 67 if (!ok)
jjg@695 68 throw new Exception("processing failed");
jjg@695 69 }
jjg@695 70
jjg@695 71 Filer filer;
jjg@695 72 Messager messager;
jjg@696 73 Trees trees;
jjg@695 74
jjg@695 75 @Override
jjg@695 76 public SourceVersion getSupportedSourceVersion() {
jjg@695 77 return SourceVersion.latest();
jjg@695 78 }
jjg@695 79
jjg@695 80 @Override
jjg@695 81 public void init(ProcessingEnvironment pEnv) {
jjg@695 82 super.init(pEnv);
jjg@695 83 filer = pEnv.getFiler();
jjg@695 84 messager = pEnv.getMessager();
jjg@696 85 trees = Trees.instance(pEnv);
jjg@695 86 }
jjg@695 87
jjg@695 88 int round = 0;
jjg@695 89
jjg@695 90 @Override
jjg@695 91 public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
jjg@695 92 round++;
jjg@695 93
jjg@695 94 // Scan trees for elements, verifying source tree positions
jjg@695 95 for (Element e: roundEnv.getRootElements()) {
jjg@695 96 try {
jjg@695 97 TreePath p = trees.getPath(e);
jjg@695 98 new TestTreeScanner(p.getCompilationUnit(), trees).scan(trees.getPath(e), null);
jjg@695 99 } catch (IOException ex) {
jjg@695 100 messager.printMessage(Diagnostic.Kind.ERROR,
jjg@695 101 "Cannot get source: " + ex, e);
jjg@695 102 }
jjg@695 103 }
jjg@695 104
jjg@695 105 final int MAXROUNDS = 3;
jjg@695 106 if (round < MAXROUNDS)
jjg@695 107 generateSource("Gen" + round);
jjg@695 108
jjg@695 109 return true;
jjg@695 110 }
jjg@695 111
jjg@695 112 void generateSource(String name) {
jjg@695 113 StringBuilder text = new StringBuilder();
jjg@695 114 text.append("class ").append(name).append("{\n");
jjg@695 115 text.append(" int one = 1;\n");
jjg@695 116 text.append(" int two = 2;\n");
jjg@695 117 text.append(" int three = one + two;\n");
jjg@695 118 text.append("}\n");
jjg@695 119
jjg@695 120 try {
jjg@695 121 JavaFileObject fo = filer.createSourceFile(name);
jjg@695 122 Writer out = fo.openWriter();
jjg@695 123 try {
jjg@695 124 out.write(text.toString());
jjg@695 125 } finally {
jjg@695 126 out.close();
jjg@695 127 }
jjg@695 128 } catch (IOException e) {
jjg@695 129 throw new Error(e);
jjg@695 130 }
jjg@695 131 }
jjg@695 132
jjg@695 133 class TestTreeScanner extends TreePathScanner<Void,Void> {
jjg@695 134 TestTreeScanner(CompilationUnitTree unit, Trees trees) throws IOException {
jjg@695 135 this.unit = unit;
jjg@695 136 JavaFileObject sf = unit.getSourceFile();
jjg@695 137 source = sf.getCharContent(true).toString();
jjg@695 138 sourcePositions = trees.getSourcePositions();
jjg@695 139 }
jjg@695 140
jjg@695 141 @Override
jjg@695 142 public Void visitVariable(VariableTree tree, Void _) {
jjg@695 143 check(getCurrentPath());
jjg@695 144 return super.visitVariable(tree, _);
jjg@695 145 }
jjg@695 146
jjg@695 147 void check(TreePath tp) {
jjg@695 148 Tree tree = tp.getLeaf();
jjg@695 149
jjg@695 150 String expect = tree.toString();
jjg@695 151 if (tree.getKind() == Tree.Kind.VARIABLE) {
jjg@695 152 // tree.toString() does not know enough context to add ";",
jjg@695 153 // so deal with that manually...
jjg@695 154 Tree.Kind enclKind = tp.getParentPath().getLeaf().getKind();
jjg@695 155 //System.err.println(" encl: " +enclKind);
jjg@695 156 if (enclKind == Tree.Kind.CLASS || enclKind == Tree.Kind.BLOCK)
jjg@695 157 expect += ";";
jjg@695 158 }
jjg@695 159 //System.err.println("expect: " + expect);
jjg@695 160
jjg@695 161 int start = (int)sourcePositions.getStartPosition(unit, tree);
jjg@695 162 if (start == Diagnostic.NOPOS) {
jjg@695 163 messager.printMessage(Diagnostic.Kind.ERROR, "start pos not set for " + trim(tree));
jjg@695 164 return;
jjg@695 165 }
jjg@695 166
jjg@695 167 int end = (int)sourcePositions.getEndPosition(unit, tree);
jjg@695 168 if (end == Diagnostic.NOPOS) {
jjg@695 169 messager.printMessage(Diagnostic.Kind.ERROR, "end pos not set for " + trim(tree));
jjg@695 170 return;
jjg@695 171 }
jjg@695 172
jjg@695 173 String found = source.substring(start, end);
jjg@695 174 //System.err.println(" found: " + found);
jjg@695 175
jjg@695 176 // allow for long lines, in which case just compare beginning and
jjg@695 177 // end of the strings
jjg@695 178 boolean equal;
jjg@695 179 if (found.contains("\n")) {
jjg@695 180 String head = found.substring(0, found.indexOf("\n"));
jjg@695 181 String tail = found.substring(found.lastIndexOf("\n")).trim();
jjg@695 182 equal = expect.startsWith(head) && expect.endsWith(tail);
jjg@695 183 } else {
jjg@695 184 equal = expect.equals(found);
jjg@695 185 }
jjg@695 186
jjg@695 187 if (!equal) {
jjg@695 188 messager.printMessage(Diagnostic.Kind.ERROR,
jjg@695 189 "unexpected value found: '" + found + "'; expected: '" + expect + "'");
jjg@695 190 }
jjg@695 191 }
jjg@695 192
jjg@695 193 String trim(Tree tree) {
jjg@695 194 final int MAXLEN = 32;
jjg@695 195 String s = tree.toString().replaceAll("\\s+", " ").trim();
jjg@695 196 return (s.length() < MAXLEN) ? s : s.substring(0, MAXLEN);
jjg@695 197
jjg@695 198 }
jjg@695 199
jjg@695 200 CompilationUnitTree unit;
jjg@695 201 SourcePositions sourcePositions;
jjg@695 202 String source;
jjg@695 203 }
jjg@695 204
jjg@695 205 }

mercurial