1 /* 2 * Copyright (c) 2010, 2019, 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 */ 23 24 /** 25 * Utility and test program to check javac's internal TreeScanner class. 26 * The program can be run standalone, or as a jtreg test. For info on 27 * command line args, run program with no args. 28 * 29 * <p> 30 * jtreg: Note that by using the -r switch in the test description below, this test 31 * will process all java files in the langtools/test directory, thus implicitly 32 * covering any new language features that may be tested in this test suite. 33 */ 34 35 /* 36 * @test 37 * @bug 6923080 38 * @summary TreeScanner.visitNewClass should scan tree.typeargs 39 * @modules jdk.compiler/com.sun.tools.javac.api 40 * jdk.compiler/com.sun.tools.javac.file 41 * jdk.compiler/com.sun.tools.javac.tree 42 * jdk.compiler/com.sun.tools.javac.util 43 * @build AbstractTreeScannerTest SourceTreeScannerTest 44 * @run main SourceTreeScannerTest -q -r . 45 */ 46 47 import java.io.*; 48 import java.lang.reflect.*; 49 import java.util.*; 50 51 import javax.tools.*; 52 53 import com.sun.source.tree.CaseTree.CaseKind; 54 import com.sun.source.tree.Tree; 55 import com.sun.source.util.JavacTask; 56 import com.sun.source.util.TreeScanner; 57 import com.sun.tools.javac.tree.JCTree; 58 import com.sun.tools.javac.tree.JCTree.JCCase; 59 import com.sun.tools.javac.tree.JCTree.JCCompilationUnit; 60 import com.sun.tools.javac.tree.JCTree.JCModuleDecl; 61 import com.sun.tools.javac.tree.JCTree.TypeBoundKind; 62 import com.sun.tools.javac.util.List; 63 import com.sun.tools.javac.util.Pair; 64 65 public class SourceTreeScannerTest extends AbstractTreeScannerTest { 66 /** 67 * Main entry point. 68 * If test.src is set, program runs in jtreg mode, and will throw an Error 69 * if any errors arise, otherwise System.exit will be used. In jtreg mode, 70 * the default base directory for file args is the value of ${test.src}. 71 * In jtreg mode, the -r option can be given to change the default base 72 * directory to the root test directory. 73 */ main(String... args)74 public static void main(String... args) { 75 String testSrc = System.getProperty("test.src"); 76 File baseDir = (testSrc == null) ? null : new File(testSrc); 77 boolean ok = new SourceTreeScannerTest().run(baseDir, args); 78 if (!ok) { 79 if (testSrc != null) // jtreg mode 80 throw new Error("failed"); 81 else 82 System.exit(1); 83 } 84 } 85 test(Pair<JavacTask, JCCompilationUnit> taskAndTree)86 int test(Pair<JavacTask, JCCompilationUnit> taskAndTree) { 87 return new ScanTester().test(taskAndTree.snd); 88 } 89 90 /** 91 * Main class for testing operation of tree scanner. 92 * The set of nodes found by the scanner are compared 93 * against the set of nodes found by reflection. 94 */ 95 private class ScanTester extends TreeScanner<Void,Void> { 96 /** Main entry method for the class. */ test(JCCompilationUnit tree)97 int test(JCCompilationUnit tree) { 98 sourcefile = tree.sourcefile; 99 found = new HashSet<Tree>(); 100 scan(tree, null); 101 expect = new HashSet<Tree>(); 102 reflectiveScan(tree); 103 104 if (found.equals(expect)) { 105 //System.err.println(sourcefile.getName() + ": trees compared OK"); 106 return found.size(); 107 } 108 109 error(sourcefile.getName() + ": differences found"); 110 111 if (found.size() != expect.size()) 112 error("Size mismatch; found: " + found.size() + ", expected: " + expect.size()); 113 114 Set<Tree> missing = new HashSet<Tree>(); 115 missing.addAll(expect); 116 missing.removeAll(found); 117 for (Tree t: missing) 118 error(sourcefile, t, "missing"); 119 120 Set<Tree> excess = new HashSet<Tree>(); 121 excess.addAll(found); 122 excess.removeAll(expect); 123 for (Tree t: excess) 124 error(sourcefile, t, "unexpected"); 125 126 return 0; 127 } 128 129 /** Record all tree nodes found by scanner. */ 130 @Override scan(Tree tree, Void ignore)131 public Void scan(Tree tree, Void ignore) { 132 if (tree == null) 133 return null; 134 //System.err.println("FOUND: " + tree.getKind() + " " + trim(tree, 64)); 135 found.add(tree); 136 return super.scan(tree, ignore); 137 } 138 139 /** record all tree nodes found by reflection. */ reflectiveScan(Object o)140 public void reflectiveScan(Object o) { 141 if (o == null) 142 return; 143 if (o instanceof JCTree) { 144 JCTree tree = (JCTree) o; 145 //System.err.println("EXPECT: " + tree.getKind() + " " + trim(tree, 64)); 146 expect.add(tree); 147 for (Field f: getFields(tree)) { 148 if (TypeBoundKind.class.isAssignableFrom(f.getType())) { 149 // not part of public API 150 continue; 151 } 152 try { 153 //System.err.println("FIELD: " + f.getName()); 154 if (tree instanceof JCModuleDecl && f.getName().equals("mods")) { 155 // The modifiers will not found by TreeScanner, 156 // but the embedded annotations will be. 157 reflectiveScan(((JCModuleDecl) tree).mods.annotations); 158 } else if (tree instanceof JCCase && 159 ((JCCase) tree).getCaseKind() == CaseKind.RULE && 160 f.getName().equals("stats")) { 161 //value case, visit value: 162 reflectiveScan(((JCCase) tree).getBody()); 163 } else { 164 reflectiveScan(f.get(tree)); 165 } 166 } catch (IllegalAccessException e) { 167 error(e.toString()); 168 } 169 } 170 } else if (o instanceof List) { 171 List<?> list = (List<?>) o; 172 for (Object item: list) 173 reflectiveScan(item); 174 } else if (o instanceof Pair) { 175 return; 176 } else 177 error("unexpected item: " + o); 178 } 179 180 JavaFileObject sourcefile; 181 Set<Tree> found; 182 Set<Tree> expect; 183 } 184 } 185