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 
32 import com.sun.source.doctree.DocCommentTree;
33 import com.sun.source.doctree.DocTree;
34 import com.sun.source.doctree.DocTree.Kind;
35 import com.sun.source.doctree.DocTreeVisitor;
36 import com.sun.source.tree.ClassTree;
37 import com.sun.source.tree.CompilationUnitTree;
38 import com.sun.source.tree.MethodTree;
39 import com.sun.source.tree.Tree;
40 import com.sun.source.tree.VariableTree;
41 import com.sun.source.util.DocTreePath;
42 import com.sun.source.util.DocTreePathScanner;
43 import com.sun.source.util.DocTreeScanner;
44 import com.sun.source.util.DocTrees;
45 import com.sun.source.util.JavacTask;
46 import com.sun.source.util.TreePath;
47 import com.sun.source.util.TreePathScanner;
48 import com.sun.tools.javac.api.JavacTool;
49 import java.io.File;
50 import java.util.ArrayList;
51 import java.util.List;
52 import javax.lang.model.element.Name;
53 import javax.tools.JavaFileObject;
54 import javax.tools.StandardJavaFileManager;
55 
56 public class DocTreePathScannerTest {
main(String... args)57     public static void main(String... args) throws Exception {
58         DocTreePathScannerTest t = new DocTreePathScannerTest();
59         t.run();
60     }
61 
run()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 
error(String msg)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 
DeclScanner(DocTrees trees)101         DeclScanner(DocTrees trees) {
102             this.trees = trees;
103             cs = new CommentPathScanner();
104         }
105 
106         @Override
visitClass(ClassTree tree, Void ignore)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
visitMethod(MethodTree tree, Void ignore)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
visitVariable(VariableTree tree, Void ignore)121         public Void visitVariable(VariableTree tree, Void ignore) {
122             super.visitVariable(tree, ignore);
123             visitDecl(tree, tree.getName());
124             return null;
125         }
126 
visitDecl(Tree tree, Name name)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> {
CommentPathScanner()136         CommentPathScanner() {}
137 
138         @Override
scan(final DocTree tree, Void ignore)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