6983239: TreeScanner does not scan default value for method

Thu, 09 Sep 2010 13:31:28 -0700

author
jjg
date
Thu, 09 Sep 2010 13:31:28 -0700
changeset 679
fc73f83cd563
parent 678
014cf6234586
child 680
80505c2026e7

6983239: TreeScanner does not scan default value for method
Reviewed-by: mcimadamore

src/share/classes/com/sun/source/util/TreeScanner.java file | annotate | diff | comparison | revisions
test/tools/javac/api/T6392782.java file | annotate | diff | comparison | revisions
test/tools/javac/tree/AbstractTreeScannerTest.java file | annotate | diff | comparison | revisions
test/tools/javac/tree/JavacTreeScannerTest.java file | annotate | diff | comparison | revisions
test/tools/javac/tree/SourceTreeScannerTest.java file | annotate | diff | comparison | revisions
test/tools/javac/tree/TreeScannerTest.java file | annotate | diff | comparison | revisions
     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 -}

mercurial