1.1 --- a/test/tools/javac/tree/TreeScannerTest.java Thu Sep 23 17:33:52 2010 -0700 1.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 1.3 @@ -1,387 +0,0 @@ 1.4 -/* 1.5 - * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. 1.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.7 - * 1.8 - * This code is free software; you can redistribute it and/or modify it 1.9 - * under the terms of the GNU General Public License version 2 only, as 1.10 - * published by the Free Software Foundation. 1.11 - * 1.12 - * This code is distributed in the hope that it will be useful, but WITHOUT 1.13 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1.14 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1.15 - * version 2 for more details (a copy is included in the LICENSE file that 1.16 - * accompanied this code). 1.17 - * 1.18 - * You should have received a copy of the GNU General Public License version 1.19 - * 2 along with this work; if not, write to the Free Software Foundation, 1.20 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 1.21 - * 1.22 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 1.23 - * or visit www.oracle.com if you need additional information or have any 1.24 - * questions. 1.25 - */ 1.26 - 1.27 - 1.28 -/** 1.29 - * Utility and test program to check javac's internal TreeScanner class. 1.30 - * The program can be run standalone, or as a jtreg test. For info on 1.31 - * command line args, run program with no args. 1.32 - * 1.33 - * <p> 1.34 - * jtreg: Note that by using the -r switch in the test description below, this test 1.35 - * will process all java files in the langtools/test directory, thus implicitly 1.36 - * covering any new language features that may be tested in this test suite. 1.37 - */ 1.38 - 1.39 -/* 1.40 - * @test 1.41 - * @bug 6923080 1.42 - * @summary TreeScanner.visitNewClass should scan tree.typeargs 1.43 - * @run main TreeScannerTest -q -r . 1.44 - */ 1.45 - 1.46 -import java.io.*; 1.47 -import java.lang.reflect.*; 1.48 -import java.util.*; 1.49 -import javax.tools.*; 1.50 - 1.51 -import com.sun.source.tree.CompilationUnitTree; 1.52 -import com.sun.source.util.JavacTask; 1.53 -import com.sun.tools.javac.api.JavacTool; 1.54 -import com.sun.tools.javac.tree.*; 1.55 -import com.sun.tools.javac.tree.JCTree.*; 1.56 -import com.sun.tools.javac.util.List; 1.57 - 1.58 -public class TreeScannerTest { 1.59 - /** 1.60 - * Main entry point. 1.61 - * If test.src is set, program runs in jtreg mode, and will throw an Error 1.62 - * if any errors arise, otherwise System.exit will be used. In jtreg mode, 1.63 - * the default base directory for file args is the value of ${test.src}. 1.64 - * In jtreg mode, the -r option can be given to change the default base 1.65 - * directory to the root test directory. 1.66 - */ 1.67 - public static void main(String... args) { 1.68 - String testSrc = System.getProperty("test.src"); 1.69 - File baseDir = (testSrc == null) ? null : new File(testSrc); 1.70 - boolean ok = new TreeScannerTest().run(baseDir, args); 1.71 - if (!ok) { 1.72 - if (testSrc != null) // jtreg mode 1.73 - throw new Error("failed"); 1.74 - else 1.75 - System.exit(1); 1.76 - } 1.77 - } 1.78 - 1.79 - /** 1.80 - * Run the program. A base directory can be provided for file arguments. 1.81 - * In jtreg mode, the -r option can be given to change the default base 1.82 - * directory to the test root directory. For other options, see usage(). 1.83 - * @param baseDir base directory for any file arguments. 1.84 - * @param args command line args 1.85 - * @return true if successful or in gui mode 1.86 - */ 1.87 - boolean run(File baseDir, String... args) { 1.88 - if (args.length == 0) { 1.89 - usage(System.out); 1.90 - return true; 1.91 - } 1.92 - 1.93 - ArrayList<File> files = new ArrayList<File>(); 1.94 - for (int i = 0; i < args.length; i++) { 1.95 - String arg = args[i]; 1.96 - if (arg.equals("-q")) 1.97 - quiet = true; 1.98 - else if (arg.equals("-v")) 1.99 - verbose = true; 1.100 - else if (arg.equals("-r")) { 1.101 - File d = baseDir; 1.102 - while (!new File(d, "TEST.ROOT").exists()) { 1.103 - d = d.getParentFile(); 1.104 - if (d == null) 1.105 - throw new Error("cannot find TEST.ROOT"); 1.106 - } 1.107 - baseDir = d; 1.108 - } 1.109 - else if (arg.startsWith("-")) 1.110 - throw new Error("unknown option: " + arg); 1.111 - else { 1.112 - while (i < args.length) 1.113 - files.add(new File(baseDir, args[i++])); 1.114 - } 1.115 - } 1.116 - 1.117 - for (File file: files) { 1.118 - if (file.exists()) 1.119 - test(file); 1.120 - else 1.121 - error("File not found: " + file); 1.122 - } 1.123 - 1.124 - if (fileCount != 1) 1.125 - System.err.println(fileCount + " files read"); 1.126 - if (errors > 0) 1.127 - System.err.println(errors + " errors"); 1.128 - 1.129 - return (errors == 0); 1.130 - } 1.131 - 1.132 - /** 1.133 - * Print command line help. 1.134 - * @param out output stream 1.135 - */ 1.136 - void usage(PrintStream out) { 1.137 - out.println("Usage:"); 1.138 - out.println(" java TreeScannerTest options... files..."); 1.139 - out.println(""); 1.140 - out.println("where options include:"); 1.141 - out.println("-q Quiet: don't report on inapplicable files"); 1.142 - out.println("-v Verbose: report on files as they are being read"); 1.143 - out.println(""); 1.144 - out.println("files may be directories or files"); 1.145 - out.println("directories will be scanned recursively"); 1.146 - out.println("non java files, or java files which cannot be parsed, will be ignored"); 1.147 - out.println(""); 1.148 - } 1.149 - 1.150 - /** 1.151 - * Test a file. If the file is a directory, it will be recursively scanned 1.152 - * for java files. 1.153 - * @param file the file or directory to test 1.154 - */ 1.155 - void test(File file) { 1.156 - if (file.isDirectory()) { 1.157 - for (File f: file.listFiles()) { 1.158 - test(f); 1.159 - } 1.160 - return; 1.161 - } 1.162 - 1.163 - if (file.isFile() && file.getName().endsWith(".java")) { 1.164 - try { 1.165 - if (verbose) 1.166 - System.err.println(file); 1.167 - fileCount++; 1.168 - ScanTester t = new ScanTester(); 1.169 - t.test(read(file)); 1.170 - } catch (ParseException e) { 1.171 - if (!quiet) { 1.172 - error("Error parsing " + file + "\n" + e.getMessage()); 1.173 - } 1.174 - } catch (IOException e) { 1.175 - error("Error reading " + file + ": " + e); 1.176 - } 1.177 - return; 1.178 - } 1.179 - 1.180 - if (!quiet) 1.181 - error("File " + file + " ignored"); 1.182 - } 1.183 - 1.184 - /** 1.185 - * Read a file. 1.186 - * @param file the file to be read 1.187 - * @return the tree for the content of the file 1.188 - * @throws IOException if any IO errors occur 1.189 - * @throws TreePosTest.ParseException if any errors occur while parsing the file 1.190 - */ 1.191 - JCCompilationUnit read(File file) throws IOException, ParseException { 1.192 - StringWriter sw = new StringWriter(); 1.193 - PrintWriter pw = new PrintWriter(sw); 1.194 - Reporter r = new Reporter(pw); 1.195 - JavacTool tool = JavacTool.create(); 1.196 - StandardJavaFileManager fm = tool.getStandardFileManager(r, null, null); 1.197 - Iterable<? extends JavaFileObject> files = fm.getJavaFileObjects(file); 1.198 - JavacTask task = tool.getTask(pw, fm, r, Collections.<String>emptyList(), null, files); 1.199 - Iterable<? extends CompilationUnitTree> trees = task.parse(); 1.200 - pw.flush(); 1.201 - if (r.errors > 0) 1.202 - throw new ParseException(sw.toString()); 1.203 - Iterator<? extends CompilationUnitTree> iter = trees.iterator(); 1.204 - if (!iter.hasNext()) 1.205 - throw new Error("no trees found"); 1.206 - JCCompilationUnit t = (JCCompilationUnit) iter.next(); 1.207 - if (iter.hasNext()) 1.208 - throw new Error("too many trees found"); 1.209 - return t; 1.210 - } 1.211 - 1.212 - /** 1.213 - * Report an error. When the program is complete, the program will either 1.214 - * exit or throw an Error if any errors have been reported. 1.215 - * @param msg the error message 1.216 - */ 1.217 - void error(String msg) { 1.218 - System.err.println(msg); 1.219 - errors++; 1.220 - } 1.221 - 1.222 - /** 1.223 - * Report an error for a specific tree node. 1.224 - * @param file the source file for the tree 1.225 - * @param t the tree node 1.226 - * @param label an indication of the error 1.227 - */ 1.228 - void error(JavaFileObject file, JCTree t, String msg) { 1.229 - error(file.getName() + ":" + getLine(file, t) + ": " + msg + " " + trim(t, 64)); 1.230 - } 1.231 - 1.232 - /** 1.233 - * Get a trimmed string for a tree node, with normalized white space and limited length. 1.234 - */ 1.235 - String trim(JCTree t, int len) { 1.236 - String s = t.toString().replaceAll("[\r\n]+", " ").replaceAll(" +", " "); 1.237 - return (s.length() < len) ? s : s.substring(0, len); 1.238 - } 1.239 - 1.240 - /** Number of files that have been analyzed. */ 1.241 - int fileCount; 1.242 - /** Number of errors reported. */ 1.243 - int errors; 1.244 - /** Flag: don't report irrelevant files. */ 1.245 - boolean quiet; 1.246 - /** Flag: report files as they are processed. */ 1.247 - boolean verbose; 1.248 - 1.249 - /** 1.250 - * Main class for testing operation of tree scanner. 1.251 - * The set of nodes found by the scanner are compared 1.252 - * against the set of nodes found by reflection. 1.253 - */ 1.254 - private class ScanTester extends TreeScanner { 1.255 - /** Main entry method for the class. */ 1.256 - void test(JCCompilationUnit tree) { 1.257 - sourcefile = tree.sourcefile; 1.258 - found = new HashSet<JCTree>(); 1.259 - scan(tree); 1.260 - expect = new HashSet<JCTree>(); 1.261 - reflectiveScan(tree); 1.262 - if (found.equals(expect)) 1.263 - return; 1.264 - 1.265 - error("Differences found for " + tree.sourcefile.getName()); 1.266 - 1.267 - if (found.size() != expect.size()) 1.268 - error("Size mismatch; found: " + found.size() + ", expected: " + expect.size()); 1.269 - 1.270 - Set<JCTree> missing = new HashSet<JCTree>(); 1.271 - missing.addAll(expect); 1.272 - missing.removeAll(found); 1.273 - for (JCTree t: missing) 1.274 - error(tree.sourcefile, t, "missing"); 1.275 - 1.276 - Set<JCTree> excess = new HashSet<JCTree>(); 1.277 - excess.addAll(found); 1.278 - excess.removeAll(expect); 1.279 - for (JCTree t: excess) 1.280 - error(tree.sourcefile, t, "unexpected"); 1.281 - } 1.282 - 1.283 - /** Record all tree nodes found by scanner. */ 1.284 - @Override 1.285 - public void scan(JCTree tree) { 1.286 - if (tree == null) 1.287 - return; 1.288 - System.err.println("FOUND: " + tree.getTag() + " " + trim(tree, 64)); 1.289 - found.add(tree); 1.290 - super.scan(tree); 1.291 - } 1.292 - 1.293 - /** record all tree nodes found by reflection. */ 1.294 - public void reflectiveScan(Object o) { 1.295 - if (o == null) 1.296 - return; 1.297 - if (o instanceof JCTree) { 1.298 - JCTree tree = (JCTree) o; 1.299 - System.err.println("EXPECT: " + tree.getTag() + " " + trim(tree, 64)); 1.300 - expect.add(tree); 1.301 - for (Field f: getFields(tree)) { 1.302 - try { 1.303 - //System.err.println("FIELD: " + f.getName()); 1.304 - reflectiveScan(f.get(tree)); 1.305 - } catch (IllegalAccessException e) { 1.306 - error(e.toString()); 1.307 - } 1.308 - } 1.309 - } else if (o instanceof List) { 1.310 - List<?> list = (List<?>) o; 1.311 - for (Object item: list) 1.312 - reflectiveScan(item); 1.313 - } else 1.314 - error("unexpected item: " + o); 1.315 - } 1.316 - 1.317 - JavaFileObject sourcefile; 1.318 - Set<JCTree> found; 1.319 - Set<JCTree> expect; 1.320 - } 1.321 - 1.322 - /** 1.323 - * Thrown when errors are found parsing a java file. 1.324 - */ 1.325 - private static class ParseException extends Exception { 1.326 - ParseException(String msg) { 1.327 - super(msg); 1.328 - } 1.329 - } 1.330 - 1.331 - /** 1.332 - * DiagnosticListener to report diagnostics and count any errors that occur. 1.333 - */ 1.334 - private static class Reporter implements DiagnosticListener<JavaFileObject> { 1.335 - Reporter(PrintWriter out) { 1.336 - this.out = out; 1.337 - } 1.338 - 1.339 - public void report(Diagnostic<? extends JavaFileObject> diagnostic) { 1.340 - out.println(diagnostic); 1.341 - switch (diagnostic.getKind()) { 1.342 - case ERROR: 1.343 - errors++; 1.344 - } 1.345 - } 1.346 - int errors; 1.347 - PrintWriter out; 1.348 - } 1.349 - 1.350 - /** 1.351 - * Get the set of fields for a tree node that may contain child tree nodes. 1.352 - * These are the fields that are subtypes of JCTree or List. 1.353 - * The results are cached, based on the tree's tag. 1.354 - */ 1.355 - Set<Field> getFields(JCTree tree) { 1.356 - Set<Field> fields = map.get(tree.getTag()); 1.357 - if (fields == null) { 1.358 - fields = new HashSet<Field>(); 1.359 - for (Field f: tree.getClass().getFields()) { 1.360 - Class<?> fc = f.getType(); 1.361 - if (JCTree.class.isAssignableFrom(fc) || List.class.isAssignableFrom(fc)) 1.362 - fields.add(f); 1.363 - } 1.364 - map.put(tree.getTag(), fields); 1.365 - } 1.366 - return fields; 1.367 - } 1.368 - // where 1.369 - Map<Integer, Set<Field>> map = new HashMap<Integer,Set<Field>>(); 1.370 - 1.371 - /** Get the line number for the primary position for a tree. 1.372 - * The code is intended to be simple, although not necessarily efficient. 1.373 - * However, note that a file manager such as JavacFileManager is likely 1.374 - * to cache the results of file.getCharContent, avoiding the need to read 1.375 - * the bits from disk each time this method is called. 1.376 - */ 1.377 - int getLine(JavaFileObject file, JCTree tree) { 1.378 - try { 1.379 - CharSequence cs = file.getCharContent(true); 1.380 - int line = 1; 1.381 - for (int i = 0; i < tree.pos; i++) { 1.382 - if (cs.charAt(i) == '\n') // jtreg tests always use Unix line endings 1.383 - line++; 1.384 - } 1.385 - return line; 1.386 - } catch (IOException e) { 1.387 - return -1; 1.388 - } 1.389 - } 1.390 -}