Thu, 09 Sep 2010 13:31:28 -0700
6983239: TreeScanner does not scan default value for method
Reviewed-by: mcimadamore
1.1 --- a/src/share/classes/com/sun/source/util/TreeScanner.java Thu Sep 09 09:42:45 2010 +0530 1.2 +++ b/src/share/classes/com/sun/source/util/TreeScanner.java Thu Sep 09 13:31:28 2010 -0700 1.3 @@ -141,6 +141,7 @@ 1.4 r = scanAndReduce(node.getReceiverAnnotations(), p, r); 1.5 r = scanAndReduce(node.getThrows(), p, r); 1.6 r = scanAndReduce(node.getBody(), p, r); 1.7 + r = scanAndReduce(node.getDefaultValue(), p, r); 1.8 return r; 1.9 } 1.10
2.1 --- a/test/tools/javac/api/T6392782.java Thu Sep 09 09:42:45 2010 +0530 2.2 +++ b/test/tools/javac/api/T6392782.java Thu Sep 09 13:31:28 2010 -0700 2.3 @@ -47,12 +47,12 @@ 2.4 check(scanner, 6, scanner.scan(trees, null)); 2.5 2.6 CountNodes nodeCounter = new CountNodes(); 2.7 - // 383 nodes with the regular parser; 384 nodes with EndPosParser 2.8 - // We automatically swith to EndPosParser when calling JavacTask.parse() 2.9 - check(nodeCounter, 384, nodeCounter.scan(trees, null)); 2.10 + // 359 nodes with the regular parser; 360 nodes with EndPosParser 2.11 + // We automatically switch to EndPosParser when calling JavacTask.parse() 2.12 + check(nodeCounter, 360, nodeCounter.scan(trees, null)); 2.13 2.14 CountIdentifiers idCounter = new CountIdentifiers(); 2.15 - check(idCounter, 106, idCounter.scan(trees, null)); 2.16 + check(idCounter, 107, idCounter.scan(trees, null)); 2.17 } 2.18 2.19 private static void check(TreeScanner<?,?> scanner, int expect, int found) { 2.20 @@ -73,10 +73,11 @@ 2.21 } 2.22 } 2.23 2.24 - // example from TreeScanner javadoc 2.25 static class CountNodes extends TreeScanner<Integer,Void> { 2.26 @Override 2.27 public Integer scan(Tree node, Void p) { 2.28 + if (node == null) 2.29 + return 0; 2.30 Integer n = super.scan(node, p); 2.31 return (n == null ? 0 : n) + 1; 2.32 }
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 3.2 +++ b/test/tools/javac/tree/AbstractTreeScannerTest.java Thu Sep 09 13:31:28 2010 -0700 3.3 @@ -0,0 +1,284 @@ 3.4 +/* 3.5 + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. 3.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3.7 + * 3.8 + * This code is free software; you can redistribute it and/or modify it 3.9 + * under the terms of the GNU General Public License version 2 only, as 3.10 + * published by the Free Software Foundation. 3.11 + * 3.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 3.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 3.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 3.15 + * version 2 for more details (a copy is included in the LICENSE file that 3.16 + * accompanied this code). 3.17 + * 3.18 + * You should have received a copy of the GNU General Public License version 3.19 + * 2 along with this work; if not, write to the Free Software Foundation, 3.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 3.21 + * 3.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 3.23 + * or visit www.oracle.com if you need additional information or have any 3.24 + * questions. 3.25 + */ 3.26 + 3.27 +import java.io.*; 3.28 +import java.lang.reflect.*; 3.29 +import java.util.*; 3.30 +import javax.tools.*; 3.31 + 3.32 +import com.sun.source.tree.CompilationUnitTree; 3.33 +import com.sun.source.tree.Tree; 3.34 +import com.sun.source.util.JavacTask; 3.35 +import com.sun.tools.javac.api.JavacTool; 3.36 +import com.sun.tools.javac.tree.JCTree; 3.37 +import com.sun.tools.javac.tree.JCTree.JCCompilationUnit; 3.38 +import com.sun.tools.javac.util.List; 3.39 + 3.40 +public abstract class AbstractTreeScannerTest { 3.41 + 3.42 + /** 3.43 + * Run the program. A base directory can be provided for file arguments. 3.44 + * In jtreg mode, the -r option can be given to change the default base 3.45 + * directory to the test root directory. For other options, see usage(). 3.46 + * @param baseDir base directory for any file arguments. 3.47 + * @param args command line args 3.48 + * @return true if successful or in gui mode 3.49 + */ 3.50 + boolean run(File baseDir, String... args) { 3.51 + if (args.length == 0) { 3.52 + usage(System.out); 3.53 + return true; 3.54 + } 3.55 + 3.56 + ArrayList<File> files = new ArrayList<File>(); 3.57 + for (int i = 0; i < args.length; i++) { 3.58 + String arg = args[i]; 3.59 + if (arg.equals("-q")) 3.60 + quiet = true; 3.61 + else if (arg.equals("-v")) 3.62 + verbose = true; 3.63 + else if (arg.equals("-r")) { 3.64 + File d = baseDir; 3.65 + while (!new File(d, "TEST.ROOT").exists()) { 3.66 + d = d.getParentFile(); 3.67 + if (d == null) 3.68 + throw new Error("cannot find TEST.ROOT"); 3.69 + } 3.70 + baseDir = d; 3.71 + } 3.72 + else if (arg.startsWith("-")) 3.73 + throw new Error("unknown option: " + arg); 3.74 + else { 3.75 + while (i < args.length) 3.76 + files.add(new File(baseDir, args[i++])); 3.77 + } 3.78 + } 3.79 + 3.80 + for (File file: files) { 3.81 + if (file.exists()) 3.82 + test(file); 3.83 + else 3.84 + error("File not found: " + file); 3.85 + } 3.86 + 3.87 + if (fileCount != 1) 3.88 + System.err.println(fileCount + " files read"); 3.89 + System.err.println(treeCount + " tree nodes compared"); 3.90 + if (errors > 0) 3.91 + System.err.println(errors + " errors"); 3.92 + 3.93 + return (errors == 0); 3.94 + } 3.95 + 3.96 + /** 3.97 + * Print command line help. 3.98 + * @param out output stream 3.99 + */ 3.100 + void usage(PrintStream out) { 3.101 + out.println("Usage:"); 3.102 + out.println(" java " + getClass().getName() + " options... files..."); 3.103 + out.println(""); 3.104 + out.println("where options include:"); 3.105 + out.println("-q Quiet: don't report on inapplicable files"); 3.106 + out.println("-v Verbose: report on files as they are being read"); 3.107 + out.println(""); 3.108 + out.println("files may be directories or files"); 3.109 + out.println("directories will be scanned recursively"); 3.110 + out.println("non java files, or java files which cannot be parsed, will be ignored"); 3.111 + out.println(""); 3.112 + } 3.113 + 3.114 + /** 3.115 + * Test a file. If the file is a directory, it will be recursively scanned 3.116 + * for java files. 3.117 + * @param file the file or directory to test 3.118 + */ 3.119 + void test(File file) { 3.120 + if (file.isDirectory()) { 3.121 + for (File f: file.listFiles()) { 3.122 + test(f); 3.123 + } 3.124 + return; 3.125 + } 3.126 + 3.127 + if (file.isFile() && file.getName().endsWith(".java")) { 3.128 + try { 3.129 + if (verbose) 3.130 + System.err.println(file); 3.131 + fileCount++; 3.132 + treeCount += test(read(file)); 3.133 + } catch (ParseException e) { 3.134 + if (!quiet) { 3.135 + error("Error parsing " + file + "\n" + e.getMessage()); 3.136 + } 3.137 + } catch (IOException e) { 3.138 + error("Error reading " + file + ": " + e); 3.139 + } 3.140 + return; 3.141 + } 3.142 + 3.143 + if (!quiet) 3.144 + error("File " + file + " ignored"); 3.145 + } 3.146 + 3.147 + abstract int test(JCCompilationUnit t); 3.148 + 3.149 + /** 3.150 + * Read a file. 3.151 + * @param file the file to be read 3.152 + * @return the tree for the content of the file 3.153 + * @throws IOException if any IO errors occur 3.154 + * @throws TreePosTest.ParseException if any errors occur while parsing the file 3.155 + */ 3.156 + JCCompilationUnit read(File file) throws IOException, ParseException { 3.157 + StringWriter sw = new StringWriter(); 3.158 + PrintWriter pw = new PrintWriter(sw); 3.159 + Reporter r = new Reporter(pw); 3.160 + JavacTool tool = JavacTool.create(); 3.161 + StandardJavaFileManager fm = tool.getStandardFileManager(r, null, null); 3.162 + Iterable<? extends JavaFileObject> files = fm.getJavaFileObjects(file); 3.163 + JavacTask task = tool.getTask(pw, fm, r, Collections.<String>emptyList(), null, files); 3.164 + Iterable<? extends CompilationUnitTree> trees = task.parse(); 3.165 + pw.flush(); 3.166 + if (r.errors > 0) 3.167 + throw new ParseException(sw.toString()); 3.168 + Iterator<? extends CompilationUnitTree> iter = trees.iterator(); 3.169 + if (!iter.hasNext()) 3.170 + throw new Error("no trees found"); 3.171 + JCCompilationUnit t = (JCCompilationUnit) iter.next(); 3.172 + if (iter.hasNext()) 3.173 + throw new Error("too many trees found"); 3.174 + return t; 3.175 + } 3.176 + 3.177 + /** 3.178 + * Report an error. When the program is complete, the program will either 3.179 + * exit or throw an Error if any errors have been reported. 3.180 + * @param msg the error message 3.181 + */ 3.182 + void error(String msg) { 3.183 + System.err.println(msg); 3.184 + errors++; 3.185 + } 3.186 + 3.187 + /** 3.188 + * Report an error for a specific tree node. 3.189 + * @param file the source file for the tree 3.190 + * @param t the tree node 3.191 + * @param label an indication of the error 3.192 + */ 3.193 + void error(JavaFileObject file, Tree tree, String msg) { 3.194 + JCTree t = (JCTree) tree; 3.195 + error(file.getName() + ":" + getLine(file, t) + ": " + msg + " " + trim(t, 64)); 3.196 + } 3.197 + 3.198 + /** 3.199 + * Get a trimmed string for a tree node, with normalized white space and limited length. 3.200 + */ 3.201 + String trim(Tree tree, int len) { 3.202 + JCTree t = (JCTree) tree; 3.203 + String s = t.toString().replaceAll("[\r\n]+", " ").replaceAll(" +", " "); 3.204 + return (s.length() < len) ? s : s.substring(0, len); 3.205 + } 3.206 + 3.207 + /** Number of files that have been analyzed. */ 3.208 + int fileCount; 3.209 + /** Number of trees that have been successfully compared. */ 3.210 + int treeCount; 3.211 + /** Number of errors reported. */ 3.212 + int errors; 3.213 + /** Flag: don't report irrelevant files. */ 3.214 + boolean quiet; 3.215 + /** Flag: report files as they are processed. */ 3.216 + boolean verbose; 3.217 + 3.218 + 3.219 + /** 3.220 + * Thrown when errors are found parsing a java file. 3.221 + */ 3.222 + private static class ParseException extends Exception { 3.223 + ParseException(String msg) { 3.224 + super(msg); 3.225 + } 3.226 + } 3.227 + 3.228 + /** 3.229 + * DiagnosticListener to report diagnostics and count any errors that occur. 3.230 + */ 3.231 + private static class Reporter implements DiagnosticListener<JavaFileObject> { 3.232 + Reporter(PrintWriter out) { 3.233 + this.out = out; 3.234 + } 3.235 + 3.236 + public void report(Diagnostic<? extends JavaFileObject> diagnostic) { 3.237 + out.println(diagnostic); 3.238 + switch (diagnostic.getKind()) { 3.239 + case ERROR: 3.240 + errors++; 3.241 + } 3.242 + } 3.243 + int errors; 3.244 + PrintWriter out; 3.245 + } 3.246 + 3.247 + /** 3.248 + * Get the set of fields for a tree node that may contain child tree nodes. 3.249 + * These are the fields that are subtypes of JCTree or List. 3.250 + * The results are cached, based on the tree's tag. 3.251 + */ 3.252 + Set<Field> getFields(JCTree tree) { 3.253 + Set<Field> fields = map.get(tree.getTag()); 3.254 + if (fields == null) { 3.255 + fields = new HashSet<Field>(); 3.256 + for (Field f: tree.getClass().getFields()) { 3.257 + Class<?> fc = f.getType(); 3.258 + if (JCTree.class.isAssignableFrom(fc) || List.class.isAssignableFrom(fc)) 3.259 + fields.add(f); 3.260 + } 3.261 + map.put(tree.getTag(), fields); 3.262 + } 3.263 + return fields; 3.264 + } 3.265 + // where 3.266 + Map<Integer, Set<Field>> map = new HashMap<Integer,Set<Field>>(); 3.267 + 3.268 + /** Get the line number for the primary position for a tree. 3.269 + * The code is intended to be simple, although not necessarily efficient. 3.270 + * However, note that a file manager such as JavacFileManager is likely 3.271 + * to cache the results of file.getCharContent, avoiding the need to read 3.272 + * the bits from disk each time this method is called. 3.273 + */ 3.274 + int getLine(JavaFileObject file, JCTree tree) { 3.275 + try { 3.276 + CharSequence cs = file.getCharContent(true); 3.277 + int line = 1; 3.278 + for (int i = 0; i < tree.pos; i++) { 3.279 + if (cs.charAt(i) == '\n') // jtreg tests always use Unix line endings 3.280 + line++; 3.281 + } 3.282 + return line; 3.283 + } catch (IOException e) { 3.284 + return -1; 3.285 + } 3.286 + } 3.287 +}
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 4.2 +++ b/test/tools/javac/tree/JavacTreeScannerTest.java Thu Sep 09 13:31:28 2010 -0700 4.3 @@ -0,0 +1,155 @@ 4.4 +/* 4.5 + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. 4.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4.7 + * 4.8 + * This code is free software; you can redistribute it and/or modify it 4.9 + * under the terms of the GNU General Public License version 2 only, as 4.10 + * published by the Free Software Foundation. 4.11 + * 4.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 4.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 4.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 4.15 + * version 2 for more details (a copy is included in the LICENSE file that 4.16 + * accompanied this code). 4.17 + * 4.18 + * You should have received a copy of the GNU General Public License version 4.19 + * 2 along with this work; if not, write to the Free Software Foundation, 4.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 4.21 + * 4.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 4.23 + * or visit www.oracle.com if you need additional information or have any 4.24 + * questions. 4.25 + */ 4.26 + 4.27 + 4.28 +/** 4.29 + * Utility and test program to check javac's internal TreeScanner class. 4.30 + * The program can be run standalone, or as a jtreg test. For info on 4.31 + * command line args, run program with no args. 4.32 + * 4.33 + * <p> 4.34 + * jtreg: Note that by using the -r switch in the test description below, this test 4.35 + * will process all java files in the langtools/test directory, thus implicitly 4.36 + * covering any new language features that may be tested in this test suite. 4.37 + */ 4.38 + 4.39 +/* 4.40 + * @test 4.41 + * @bug 6923080 4.42 + * @summary TreeScanner.visitNewClass should scan tree.typeargs 4.43 + * @build AbstractTreeScannerTest JavacTreeScannerTest 4.44 + * @run main JavacTreeScannerTest -q -r . 4.45 + */ 4.46 + 4.47 +import java.io.*; 4.48 +import java.lang.reflect.*; 4.49 +import java.util.*; 4.50 +import javax.tools.*; 4.51 + 4.52 +import com.sun.tools.javac.tree.JCTree; 4.53 +import com.sun.tools.javac.tree.JCTree.JCCompilationUnit; 4.54 +import com.sun.tools.javac.tree.TreeScanner; 4.55 +import com.sun.tools.javac.util.List; 4.56 + 4.57 +public class JavacTreeScannerTest extends AbstractTreeScannerTest { 4.58 + /** 4.59 + * Main entry point. 4.60 + * If test.src is set, program runs in jtreg mode, and will throw an Error 4.61 + * if any errors arise, otherwise System.exit will be used. In jtreg mode, 4.62 + * the default base directory for file args is the value of ${test.src}. 4.63 + * In jtreg mode, the -r option can be given to change the default base 4.64 + * directory to the root test directory. 4.65 + */ 4.66 + public static void main(String... args) { 4.67 + String testSrc = System.getProperty("test.src"); 4.68 + File baseDir = (testSrc == null) ? null : new File(testSrc); 4.69 + boolean ok = new JavacTreeScannerTest().run(baseDir, args); 4.70 + if (!ok) { 4.71 + if (testSrc != null) // jtreg mode 4.72 + throw new Error("failed"); 4.73 + else 4.74 + System.exit(1); 4.75 + } 4.76 + } 4.77 + 4.78 + int test(JCCompilationUnit tree) { 4.79 + return new ScanTester().test(tree); 4.80 + } 4.81 + 4.82 + /** 4.83 + * Main class for testing operation of tree scanner. 4.84 + * The set of nodes found by the scanner are compared 4.85 + * against the set of nodes found by reflection. 4.86 + */ 4.87 + private class ScanTester extends TreeScanner { 4.88 + /** Main entry method for the class. */ 4.89 + int test(JCCompilationUnit tree) { 4.90 + sourcefile = tree.sourcefile; 4.91 + found = new HashSet<JCTree>(); 4.92 + scan(tree); 4.93 + expect = new HashSet<JCTree>(); 4.94 + reflectiveScan(tree); 4.95 + if (found.equals(expect)) { 4.96 + System.err.println(found.size() + " trees compared OK"); 4.97 + return found.size(); 4.98 + } 4.99 + 4.100 + error("Differences found for " + tree.sourcefile.getName()); 4.101 + 4.102 + if (found.size() != expect.size()) 4.103 + error("Size mismatch; found: " + found.size() + ", expected: " + expect.size()); 4.104 + 4.105 + Set<JCTree> missing = new HashSet<JCTree>(); 4.106 + missing.addAll(expect); 4.107 + missing.removeAll(found); 4.108 + for (JCTree t: missing) 4.109 + error(tree.sourcefile, t, "missing"); 4.110 + 4.111 + Set<JCTree> excess = new HashSet<JCTree>(); 4.112 + excess.addAll(found); 4.113 + excess.removeAll(expect); 4.114 + for (JCTree t: excess) 4.115 + error(tree.sourcefile, t, "unexpected"); 4.116 + 4.117 + return 0; 4.118 + } 4.119 + 4.120 + /** Record all tree nodes found by scanner. */ 4.121 + @Override 4.122 + public void scan(JCTree tree) { 4.123 + if (tree == null) 4.124 + return; 4.125 + System.err.println("FOUND: " + tree.getTag() + " " + trim(tree, 64)); 4.126 + found.add(tree); 4.127 + super.scan(tree); 4.128 + } 4.129 + 4.130 + /** record all tree nodes found by reflection. */ 4.131 + public void reflectiveScan(Object o) { 4.132 + if (o == null) 4.133 + return; 4.134 + if (o instanceof JCTree) { 4.135 + JCTree tree = (JCTree) o; 4.136 + System.err.println("EXPECT: " + tree.getTag() + " " + trim(tree, 64)); 4.137 + expect.add(tree); 4.138 + for (Field f: getFields(tree)) { 4.139 + try { 4.140 + //System.err.println("FIELD: " + f.getName()); 4.141 + reflectiveScan(f.get(tree)); 4.142 + } catch (IllegalAccessException e) { 4.143 + error(e.toString()); 4.144 + } 4.145 + } 4.146 + } else if (o instanceof List) { 4.147 + List<?> list = (List<?>) o; 4.148 + for (Object item: list) 4.149 + reflectiveScan(item); 4.150 + } else 4.151 + error("unexpected item: " + o); 4.152 + } 4.153 + 4.154 + JavaFileObject sourcefile; 4.155 + Set<JCTree> found; 4.156 + Set<JCTree> expect; 4.157 + } 4.158 +}
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 5.2 +++ b/test/tools/javac/tree/SourceTreeScannerTest.java Thu Sep 09 13:31:28 2010 -0700 5.3 @@ -0,0 +1,168 @@ 5.4 +/* 5.5 + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. 5.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 5.7 + * 5.8 + * This code is free software; you can redistribute it and/or modify it 5.9 + * under the terms of the GNU General Public License version 2 only, as 5.10 + * published by the Free Software Foundation. 5.11 + * 5.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 5.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 5.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 5.15 + * version 2 for more details (a copy is included in the LICENSE file that 5.16 + * accompanied this code). 5.17 + * 5.18 + * You should have received a copy of the GNU General Public License version 5.19 + * 2 along with this work; if not, write to the Free Software Foundation, 5.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 5.21 + * 5.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 5.23 + * or visit www.oracle.com if you need additional information or have any 5.24 + * questions. 5.25 + */ 5.26 + 5.27 + 5.28 +/** 5.29 + * Utility and test program to check javac's internal TreeScanner class. 5.30 + * The program can be run standalone, or as a jtreg test. For info on 5.31 + * command line args, run program with no args. 5.32 + * 5.33 + * <p> 5.34 + * jtreg: Note that by using the -r switch in the test description below, this test 5.35 + * will process all java files in the langtools/test directory, thus implicitly 5.36 + * covering any new language features that may be tested in this test suite. 5.37 + */ 5.38 + 5.39 +/* 5.40 + * @test 5.41 + * @bug 6923080 5.42 + * @summary TreeScanner.visitNewClass should scan tree.typeargs 5.43 + * @build AbstractTreeScannerTest SourceTreeScannerTest 5.44 + * @run main SourceTreeScannerTest -q -r . 5.45 + */ 5.46 + 5.47 +import java.io.*; 5.48 +import java.lang.reflect.*; 5.49 +import java.util.*; 5.50 +import javax.tools.*; 5.51 + 5.52 +import com.sun.source.tree.Tree; 5.53 +import com.sun.source.util.TreeScanner; 5.54 +import com.sun.tools.javac.tree.JCTree; 5.55 +import com.sun.tools.javac.tree.JCTree.JCCompilationUnit; 5.56 +import com.sun.tools.javac.tree.JCTree.TypeBoundKind; 5.57 +import com.sun.tools.javac.util.List; 5.58 + 5.59 +public class SourceTreeScannerTest extends AbstractTreeScannerTest { 5.60 + /** 5.61 + * Main entry point. 5.62 + * If test.src is set, program runs in jtreg mode, and will throw an Error 5.63 + * if any errors arise, otherwise System.exit will be used. In jtreg mode, 5.64 + * the default base directory for file args is the value of ${test.src}. 5.65 + * In jtreg mode, the -r option can be given to change the default base 5.66 + * directory to the root test directory. 5.67 + */ 5.68 + public static void main(String... args) { 5.69 + String testSrc = System.getProperty("test.src"); 5.70 + File baseDir = (testSrc == null) ? null : new File(testSrc); 5.71 + boolean ok = new SourceTreeScannerTest().run(baseDir, args); 5.72 + if (!ok) { 5.73 + if (testSrc != null) // jtreg mode 5.74 + throw new Error("failed"); 5.75 + else 5.76 + System.exit(1); 5.77 + } 5.78 + } 5.79 + 5.80 + int test(JCCompilationUnit tree) { 5.81 + return new ScanTester().test(tree); 5.82 + } 5.83 + 5.84 + /** 5.85 + * Main class for testing operation of tree scanner. 5.86 + * The set of nodes found by the scanner are compared 5.87 + * against the set of nodes found by reflection. 5.88 + */ 5.89 + private class ScanTester extends TreeScanner<Void,Void> { 5.90 + /** Main entry method for the class. */ 5.91 + int test(JCCompilationUnit tree) { 5.92 + sourcefile = tree.sourcefile; 5.93 + found = new HashSet<Tree>(); 5.94 + scan(tree, null); 5.95 + expect = new HashSet<Tree>(); 5.96 + reflectiveScan(tree); 5.97 + if (found.equals(expect)) { 5.98 + System.err.println(found.size() + " trees compared OK"); 5.99 + return found.size(); 5.100 + } 5.101 + 5.102 + error("Differences found for " + tree.sourcefile.getName()); 5.103 + 5.104 + if (found.size() != expect.size()) 5.105 + error("Size mismatch; found: " + found.size() + ", expected: " + expect.size()); 5.106 + 5.107 + Set<Tree> missing = new HashSet<Tree>(); 5.108 + missing.addAll(expect); 5.109 + missing.removeAll(found); 5.110 + for (Tree t: missing) 5.111 + error(tree.sourcefile, t, "missing"); 5.112 + 5.113 + Set<Tree> excess = new HashSet<Tree>(); 5.114 + excess.addAll(found); 5.115 + excess.removeAll(expect); 5.116 + for (Tree t: excess) 5.117 + error(tree.sourcefile, t, "unexpected"); 5.118 + 5.119 + return 0; 5.120 + } 5.121 + 5.122 + /** Record all tree nodes found by scanner. */ 5.123 + @Override 5.124 + public Void scan(Tree tree, Void ignore) { 5.125 + if (tree == null) 5.126 + return null; 5.127 + System.err.println("FOUND: " + tree.getKind() + " " + trim(tree, 64)); 5.128 + found.add(tree); 5.129 + return super.scan(tree, ignore); 5.130 + } 5.131 + 5.132 + /** record all tree nodes found by reflection. */ 5.133 + public void reflectiveScan(Object o) { 5.134 + if (o == null) 5.135 + return; 5.136 + if (o instanceof JCTree) { 5.137 + JCTree tree = (JCTree) o; 5.138 + System.err.println("EXPECT: " + tree.getKind() + " " + trim(tree, 64)); 5.139 + expect.add(tree); 5.140 + for (Field f: getFields(tree)) { 5.141 + if (TypeBoundKind.class.isAssignableFrom(f.getType())) { 5.142 + // not part of public API 5.143 + continue; 5.144 + } 5.145 + if (JCTree.JCNewArray.class.isAssignableFrom(tree.getClass()) 5.146 + && (f.getName().equals("annotations") 5.147 + || f.getName().equals("dimAnnotations"))) { 5.148 + // these fields are incorrectly missing from the public API 5.149 + // (CR 6983297) 5.150 + continue; 5.151 + } 5.152 + try { 5.153 + //System.err.println("FIELD: " + f.getName()); 5.154 + reflectiveScan(f.get(tree)); 5.155 + } catch (IllegalAccessException e) { 5.156 + error(e.toString()); 5.157 + } 5.158 + } 5.159 + } else if (o instanceof List) { 5.160 + List<?> list = (List<?>) o; 5.161 + for (Object item: list) 5.162 + reflectiveScan(item); 5.163 + } else 5.164 + error("unexpected item: " + o); 5.165 + } 5.166 + 5.167 + JavaFileObject sourcefile; 5.168 + Set<Tree> found; 5.169 + Set<Tree> expect; 5.170 + } 5.171 +}
6.1 --- a/test/tools/javac/tree/TreeScannerTest.java Thu Sep 09 09:42:45 2010 +0530 6.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 6.3 @@ -1,387 +0,0 @@ 6.4 -/* 6.5 - * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. 6.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 6.7 - * 6.8 - * This code is free software; you can redistribute it and/or modify it 6.9 - * under the terms of the GNU General Public License version 2 only, as 6.10 - * published by the Free Software Foundation. 6.11 - * 6.12 - * This code is distributed in the hope that it will be useful, but WITHOUT 6.13 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 6.14 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 6.15 - * version 2 for more details (a copy is included in the LICENSE file that 6.16 - * accompanied this code). 6.17 - * 6.18 - * You should have received a copy of the GNU General Public License version 6.19 - * 2 along with this work; if not, write to the Free Software Foundation, 6.20 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 6.21 - * 6.22 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 6.23 - * or visit www.oracle.com if you need additional information or have any 6.24 - * questions. 6.25 - */ 6.26 - 6.27 - 6.28 -/** 6.29 - * Utility and test program to check javac's internal TreeScanner class. 6.30 - * The program can be run standalone, or as a jtreg test. For info on 6.31 - * command line args, run program with no args. 6.32 - * 6.33 - * <p> 6.34 - * jtreg: Note that by using the -r switch in the test description below, this test 6.35 - * will process all java files in the langtools/test directory, thus implicitly 6.36 - * covering any new language features that may be tested in this test suite. 6.37 - */ 6.38 - 6.39 -/* 6.40 - * @test 6.41 - * @bug 6923080 6.42 - * @summary TreeScanner.visitNewClass should scan tree.typeargs 6.43 - * @run main TreeScannerTest -q -r . 6.44 - */ 6.45 - 6.46 -import java.io.*; 6.47 -import java.lang.reflect.*; 6.48 -import java.util.*; 6.49 -import javax.tools.*; 6.50 - 6.51 -import com.sun.source.tree.CompilationUnitTree; 6.52 -import com.sun.source.util.JavacTask; 6.53 -import com.sun.tools.javac.api.JavacTool; 6.54 -import com.sun.tools.javac.tree.*; 6.55 -import com.sun.tools.javac.tree.JCTree.*; 6.56 -import com.sun.tools.javac.util.List; 6.57 - 6.58 -public class TreeScannerTest { 6.59 - /** 6.60 - * Main entry point. 6.61 - * If test.src is set, program runs in jtreg mode, and will throw an Error 6.62 - * if any errors arise, otherwise System.exit will be used. In jtreg mode, 6.63 - * the default base directory for file args is the value of ${test.src}. 6.64 - * In jtreg mode, the -r option can be given to change the default base 6.65 - * directory to the root test directory. 6.66 - */ 6.67 - public static void main(String... args) { 6.68 - String testSrc = System.getProperty("test.src"); 6.69 - File baseDir = (testSrc == null) ? null : new File(testSrc); 6.70 - boolean ok = new TreeScannerTest().run(baseDir, args); 6.71 - if (!ok) { 6.72 - if (testSrc != null) // jtreg mode 6.73 - throw new Error("failed"); 6.74 - else 6.75 - System.exit(1); 6.76 - } 6.77 - } 6.78 - 6.79 - /** 6.80 - * Run the program. A base directory can be provided for file arguments. 6.81 - * In jtreg mode, the -r option can be given to change the default base 6.82 - * directory to the test root directory. For other options, see usage(). 6.83 - * @param baseDir base directory for any file arguments. 6.84 - * @param args command line args 6.85 - * @return true if successful or in gui mode 6.86 - */ 6.87 - boolean run(File baseDir, String... args) { 6.88 - if (args.length == 0) { 6.89 - usage(System.out); 6.90 - return true; 6.91 - } 6.92 - 6.93 - ArrayList<File> files = new ArrayList<File>(); 6.94 - for (int i = 0; i < args.length; i++) { 6.95 - String arg = args[i]; 6.96 - if (arg.equals("-q")) 6.97 - quiet = true; 6.98 - else if (arg.equals("-v")) 6.99 - verbose = true; 6.100 - else if (arg.equals("-r")) { 6.101 - File d = baseDir; 6.102 - while (!new File(d, "TEST.ROOT").exists()) { 6.103 - d = d.getParentFile(); 6.104 - if (d == null) 6.105 - throw new Error("cannot find TEST.ROOT"); 6.106 - } 6.107 - baseDir = d; 6.108 - } 6.109 - else if (arg.startsWith("-")) 6.110 - throw new Error("unknown option: " + arg); 6.111 - else { 6.112 - while (i < args.length) 6.113 - files.add(new File(baseDir, args[i++])); 6.114 - } 6.115 - } 6.116 - 6.117 - for (File file: files) { 6.118 - if (file.exists()) 6.119 - test(file); 6.120 - else 6.121 - error("File not found: " + file); 6.122 - } 6.123 - 6.124 - if (fileCount != 1) 6.125 - System.err.println(fileCount + " files read"); 6.126 - if (errors > 0) 6.127 - System.err.println(errors + " errors"); 6.128 - 6.129 - return (errors == 0); 6.130 - } 6.131 - 6.132 - /** 6.133 - * Print command line help. 6.134 - * @param out output stream 6.135 - */ 6.136 - void usage(PrintStream out) { 6.137 - out.println("Usage:"); 6.138 - out.println(" java TreeScannerTest options... files..."); 6.139 - out.println(""); 6.140 - out.println("where options include:"); 6.141 - out.println("-q Quiet: don't report on inapplicable files"); 6.142 - out.println("-v Verbose: report on files as they are being read"); 6.143 - out.println(""); 6.144 - out.println("files may be directories or files"); 6.145 - out.println("directories will be scanned recursively"); 6.146 - out.println("non java files, or java files which cannot be parsed, will be ignored"); 6.147 - out.println(""); 6.148 - } 6.149 - 6.150 - /** 6.151 - * Test a file. If the file is a directory, it will be recursively scanned 6.152 - * for java files. 6.153 - * @param file the file or directory to test 6.154 - */ 6.155 - void test(File file) { 6.156 - if (file.isDirectory()) { 6.157 - for (File f: file.listFiles()) { 6.158 - test(f); 6.159 - } 6.160 - return; 6.161 - } 6.162 - 6.163 - if (file.isFile() && file.getName().endsWith(".java")) { 6.164 - try { 6.165 - if (verbose) 6.166 - System.err.println(file); 6.167 - fileCount++; 6.168 - ScanTester t = new ScanTester(); 6.169 - t.test(read(file)); 6.170 - } catch (ParseException e) { 6.171 - if (!quiet) { 6.172 - error("Error parsing " + file + "\n" + e.getMessage()); 6.173 - } 6.174 - } catch (IOException e) { 6.175 - error("Error reading " + file + ": " + e); 6.176 - } 6.177 - return; 6.178 - } 6.179 - 6.180 - if (!quiet) 6.181 - error("File " + file + " ignored"); 6.182 - } 6.183 - 6.184 - /** 6.185 - * Read a file. 6.186 - * @param file the file to be read 6.187 - * @return the tree for the content of the file 6.188 - * @throws IOException if any IO errors occur 6.189 - * @throws TreePosTest.ParseException if any errors occur while parsing the file 6.190 - */ 6.191 - JCCompilationUnit read(File file) throws IOException, ParseException { 6.192 - StringWriter sw = new StringWriter(); 6.193 - PrintWriter pw = new PrintWriter(sw); 6.194 - Reporter r = new Reporter(pw); 6.195 - JavacTool tool = JavacTool.create(); 6.196 - StandardJavaFileManager fm = tool.getStandardFileManager(r, null, null); 6.197 - Iterable<? extends JavaFileObject> files = fm.getJavaFileObjects(file); 6.198 - JavacTask task = tool.getTask(pw, fm, r, Collections.<String>emptyList(), null, files); 6.199 - Iterable<? extends CompilationUnitTree> trees = task.parse(); 6.200 - pw.flush(); 6.201 - if (r.errors > 0) 6.202 - throw new ParseException(sw.toString()); 6.203 - Iterator<? extends CompilationUnitTree> iter = trees.iterator(); 6.204 - if (!iter.hasNext()) 6.205 - throw new Error("no trees found"); 6.206 - JCCompilationUnit t = (JCCompilationUnit) iter.next(); 6.207 - if (iter.hasNext()) 6.208 - throw new Error("too many trees found"); 6.209 - return t; 6.210 - } 6.211 - 6.212 - /** 6.213 - * Report an error. When the program is complete, the program will either 6.214 - * exit or throw an Error if any errors have been reported. 6.215 - * @param msg the error message 6.216 - */ 6.217 - void error(String msg) { 6.218 - System.err.println(msg); 6.219 - errors++; 6.220 - } 6.221 - 6.222 - /** 6.223 - * Report an error for a specific tree node. 6.224 - * @param file the source file for the tree 6.225 - * @param t the tree node 6.226 - * @param label an indication of the error 6.227 - */ 6.228 - void error(JavaFileObject file, JCTree t, String msg) { 6.229 - error(file.getName() + ":" + getLine(file, t) + ": " + msg + " " + trim(t, 64)); 6.230 - } 6.231 - 6.232 - /** 6.233 - * Get a trimmed string for a tree node, with normalized white space and limited length. 6.234 - */ 6.235 - String trim(JCTree t, int len) { 6.236 - String s = t.toString().replaceAll("[\r\n]+", " ").replaceAll(" +", " "); 6.237 - return (s.length() < len) ? s : s.substring(0, len); 6.238 - } 6.239 - 6.240 - /** Number of files that have been analyzed. */ 6.241 - int fileCount; 6.242 - /** Number of errors reported. */ 6.243 - int errors; 6.244 - /** Flag: don't report irrelevant files. */ 6.245 - boolean quiet; 6.246 - /** Flag: report files as they are processed. */ 6.247 - boolean verbose; 6.248 - 6.249 - /** 6.250 - * Main class for testing operation of tree scanner. 6.251 - * The set of nodes found by the scanner are compared 6.252 - * against the set of nodes found by reflection. 6.253 - */ 6.254 - private class ScanTester extends TreeScanner { 6.255 - /** Main entry method for the class. */ 6.256 - void test(JCCompilationUnit tree) { 6.257 - sourcefile = tree.sourcefile; 6.258 - found = new HashSet<JCTree>(); 6.259 - scan(tree); 6.260 - expect = new HashSet<JCTree>(); 6.261 - reflectiveScan(tree); 6.262 - if (found.equals(expect)) 6.263 - return; 6.264 - 6.265 - error("Differences found for " + tree.sourcefile.getName()); 6.266 - 6.267 - if (found.size() != expect.size()) 6.268 - error("Size mismatch; found: " + found.size() + ", expected: " + expect.size()); 6.269 - 6.270 - Set<JCTree> missing = new HashSet<JCTree>(); 6.271 - missing.addAll(expect); 6.272 - missing.removeAll(found); 6.273 - for (JCTree t: missing) 6.274 - error(tree.sourcefile, t, "missing"); 6.275 - 6.276 - Set<JCTree> excess = new HashSet<JCTree>(); 6.277 - excess.addAll(found); 6.278 - excess.removeAll(expect); 6.279 - for (JCTree t: excess) 6.280 - error(tree.sourcefile, t, "unexpected"); 6.281 - } 6.282 - 6.283 - /** Record all tree nodes found by scanner. */ 6.284 - @Override 6.285 - public void scan(JCTree tree) { 6.286 - if (tree == null) 6.287 - return; 6.288 - System.err.println("FOUND: " + tree.getTag() + " " + trim(tree, 64)); 6.289 - found.add(tree); 6.290 - super.scan(tree); 6.291 - } 6.292 - 6.293 - /** record all tree nodes found by reflection. */ 6.294 - public void reflectiveScan(Object o) { 6.295 - if (o == null) 6.296 - return; 6.297 - if (o instanceof JCTree) { 6.298 - JCTree tree = (JCTree) o; 6.299 - System.err.println("EXPECT: " + tree.getTag() + " " + trim(tree, 64)); 6.300 - expect.add(tree); 6.301 - for (Field f: getFields(tree)) { 6.302 - try { 6.303 - //System.err.println("FIELD: " + f.getName()); 6.304 - reflectiveScan(f.get(tree)); 6.305 - } catch (IllegalAccessException e) { 6.306 - error(e.toString()); 6.307 - } 6.308 - } 6.309 - } else if (o instanceof List) { 6.310 - List<?> list = (List<?>) o; 6.311 - for (Object item: list) 6.312 - reflectiveScan(item); 6.313 - } else 6.314 - error("unexpected item: " + o); 6.315 - } 6.316 - 6.317 - JavaFileObject sourcefile; 6.318 - Set<JCTree> found; 6.319 - Set<JCTree> expect; 6.320 - } 6.321 - 6.322 - /** 6.323 - * Thrown when errors are found parsing a java file. 6.324 - */ 6.325 - private static class ParseException extends Exception { 6.326 - ParseException(String msg) { 6.327 - super(msg); 6.328 - } 6.329 - } 6.330 - 6.331 - /** 6.332 - * DiagnosticListener to report diagnostics and count any errors that occur. 6.333 - */ 6.334 - private static class Reporter implements DiagnosticListener<JavaFileObject> { 6.335 - Reporter(PrintWriter out) { 6.336 - this.out = out; 6.337 - } 6.338 - 6.339 - public void report(Diagnostic<? extends JavaFileObject> diagnostic) { 6.340 - out.println(diagnostic); 6.341 - switch (diagnostic.getKind()) { 6.342 - case ERROR: 6.343 - errors++; 6.344 - } 6.345 - } 6.346 - int errors; 6.347 - PrintWriter out; 6.348 - } 6.349 - 6.350 - /** 6.351 - * Get the set of fields for a tree node that may contain child tree nodes. 6.352 - * These are the fields that are subtypes of JCTree or List. 6.353 - * The results are cached, based on the tree's tag. 6.354 - */ 6.355 - Set<Field> getFields(JCTree tree) { 6.356 - Set<Field> fields = map.get(tree.getTag()); 6.357 - if (fields == null) { 6.358 - fields = new HashSet<Field>(); 6.359 - for (Field f: tree.getClass().getFields()) { 6.360 - Class<?> fc = f.getType(); 6.361 - if (JCTree.class.isAssignableFrom(fc) || List.class.isAssignableFrom(fc)) 6.362 - fields.add(f); 6.363 - } 6.364 - map.put(tree.getTag(), fields); 6.365 - } 6.366 - return fields; 6.367 - } 6.368 - // where 6.369 - Map<Integer, Set<Field>> map = new HashMap<Integer,Set<Field>>(); 6.370 - 6.371 - /** Get the line number for the primary position for a tree. 6.372 - * The code is intended to be simple, although not necessarily efficient. 6.373 - * However, note that a file manager such as JavacFileManager is likely 6.374 - * to cache the results of file.getCharContent, avoiding the need to read 6.375 - * the bits from disk each time this method is called. 6.376 - */ 6.377 - int getLine(JavaFileObject file, JCTree tree) { 6.378 - try { 6.379 - CharSequence cs = file.getCharContent(true); 6.380 - int line = 1; 6.381 - for (int i = 0; i < tree.pos; i++) { 6.382 - if (cs.charAt(i) == '\n') // jtreg tests always use Unix line endings 6.383 - line++; 6.384 - } 6.385 - return line; 6.386 - } catch (IOException e) { 6.387 - return -1; 6.388 - } 6.389 - } 6.390 -}