1/*
2 * Copyright (c) 2013, 2015, 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 * @test
26 * @bug 8009724
27 * @summary adding DocTreePath and DocTreePathScanner
28 * @modules jdk.compiler/com.sun.tools.javac.api
29 *          jdk.compiler/com.sun.tools.javac.file
30 */
31
32import com.sun.source.doctree.DocCommentTree;
33import com.sun.source.doctree.DocTree;
34import com.sun.source.doctree.DocTree.Kind;
35import com.sun.source.doctree.DocTreeVisitor;
36import com.sun.source.tree.ClassTree;
37import com.sun.source.tree.CompilationUnitTree;
38import com.sun.source.tree.MethodTree;
39import com.sun.source.tree.Tree;
40import com.sun.source.tree.VariableTree;
41import com.sun.source.util.DocTreePath;
42import com.sun.source.util.DocTreePathScanner;
43import com.sun.source.util.DocTreeScanner;
44import com.sun.source.util.DocTrees;
45import com.sun.source.util.JavacTask;
46import com.sun.source.util.TreePath;
47import com.sun.source.util.TreePathScanner;
48import com.sun.tools.javac.api.JavacTool;
49import java.io.File;
50import java.util.ArrayList;
51import java.util.List;
52import javax.lang.model.element.Name;
53import javax.tools.JavaFileObject;
54import javax.tools.StandardJavaFileManager;
55
56public class DocTreePathScannerTest {
57    public static void main(String... args) throws Exception {
58        DocTreePathScannerTest t = new DocTreePathScannerTest();
59        t.run();
60    }
61
62    void run() throws Exception {
63        List<File> files = new ArrayList<File>();
64        File testSrc = new File(System.getProperty("test.src"));
65        for (File f: testSrc.listFiles()) {
66            if (f.isFile() && f.getName().endsWith(".java"))
67                files.add(f);
68        }
69
70        JavacTool javac = JavacTool.create();
71        try (StandardJavaFileManager fm = javac.getStandardFileManager(null, null, null)) {
72
73            Iterable<? extends JavaFileObject> fos = fm.getJavaFileObjectsFromFiles(files);
74
75            JavacTask t = javac.getTask(null, fm, null, null, null, fos);
76            DocTrees trees = DocTrees.instance(t);
77
78            Iterable<? extends CompilationUnitTree> units = t.parse();
79
80            DeclScanner ds = new DeclScanner(trees);
81            for (CompilationUnitTree unit: units) {
82                ds.scan(unit, null);
83            }
84
85            if (errors > 0)
86                throw new Exception(errors + " errors occurred");
87        }
88    }
89
90    void error(String msg) {
91        System.err.println("Error: " + msg);
92        errors++;
93    }
94
95    int errors;
96
97    class DeclScanner extends TreePathScanner<Void, Void> {
98        DocTrees trees;
99        DocTreePathScanner<Void,Void> cs;
100
101        DeclScanner(DocTrees trees) {
102            this.trees = trees;
103            cs = new CommentPathScanner();
104        }
105
106        @Override
107        public Void visitClass(ClassTree tree, Void ignore) {
108            super.visitClass(tree, ignore);
109            visitDecl(tree, tree.getSimpleName());
110            return null;
111        }
112
113        @Override
114        public Void visitMethod(MethodTree tree, Void ignore) {
115            super.visitMethod(tree, ignore);
116            visitDecl(tree, tree.getName());
117            return null;
118        }
119
120        @Override
121        public Void visitVariable(VariableTree tree, Void ignore) {
122            super.visitVariable(tree, ignore);
123            visitDecl(tree, tree.getName());
124            return null;
125        }
126
127        void visitDecl(Tree tree, Name name) {
128            TreePath path = getCurrentPath();
129            DocCommentTree dc = trees.getDocCommentTree(path);
130            if (dc != null)
131                cs.scan(new DocTreePath(path, dc), null);
132        }
133    }
134
135    class CommentPathScanner extends DocTreePathScanner<Void, Void> {
136        CommentPathScanner() {}
137
138        @Override
139        public Void scan(final DocTree tree, Void ignore) {
140            if (tree != null) {
141                DocTree previous = null;
142                for (DocTree current : getCurrentPath()) {
143                    if (previous != null) {
144                        final List<DocTree> children = new ArrayList<>();
145                        current.accept(new DocTreeScanner<Void, Void>() {
146                            @Override public Void scan(DocTree node, Void p) {
147                                children.add(node);
148                                return null;
149                            }
150                        }, null);
151
152                        if (!children.contains(previous)) {
153                            error("Invalid DocTreePath for: " + tree);
154                        }
155                    }
156
157                    previous = current;
158                }
159            }
160            return super.scan(tree, ignore);
161        }
162    }
163
164}
165