Mon, 06 May 2013 16:22:45 +0200
8009724: Enhance the DocTree API with DocTreePath
Summary: Adding DocTreePath and DocTreePathScanner similar to TreePath and TreePathScanner, respectively
Reviewed-by: jjg
Contributed-by: Ralph Benjamin Ruijs <ralphbenjamin@netbeans.org>, Jan Lahoda <jlahoda@netbeans.org>
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/share/classes/com/sun/source/util/DocTreePath.java Mon May 06 16:22:45 2013 +0200 1.3 @@ -0,0 +1,171 @@ 1.4 +/* 1.5 + * Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved. 1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.7 + * 1.8 + * This code is free software; you can redistribute it and/or modify it 1.9 + * under the terms of the GNU General Public License version 2 only, as 1.10 + * published by the Free Software Foundation. Oracle designates this 1.11 + * particular file as subject to the "Classpath" exception as provided 1.12 + * by Oracle in the LICENSE file that accompanied this code. 1.13 + * 1.14 + * This code is distributed in the hope that it will be useful, but WITHOUT 1.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1.17 + * version 2 for more details (a copy is included in the LICENSE file that 1.18 + * accompanied this code). 1.19 + * 1.20 + * You should have received a copy of the GNU General Public License version 1.21 + * 2 along with this work; if not, write to the Free Software Foundation, 1.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 1.23 + * 1.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 1.25 + * or visit www.oracle.com if you need additional information or have any 1.26 + * questions. 1.27 + */ 1.28 + 1.29 +package com.sun.source.util; 1.30 + 1.31 +import com.sun.source.doctree.DocCommentTree; 1.32 +import com.sun.source.doctree.DocTree; 1.33 +import java.util.Iterator; 1.34 + 1.35 +/** 1.36 + * A path of tree nodes, typically used to represent the sequence of ancestor 1.37 + * nodes of a tree node up to the top level DocCommentTree node. 1.38 + * 1.39 + * @since 1.8 1.40 + */ 1.41 +@jdk.Supported 1.42 +public class DocTreePath implements Iterable<DocTree> { 1.43 + /** 1.44 + * Gets a documentation tree path for a tree node within a compilation unit. 1.45 + * @return null if the node is not found 1.46 + */ 1.47 + public static DocTreePath getPath(TreePath treePath, DocCommentTree doc, DocTree target) { 1.48 + return getPath(new DocTreePath(treePath, doc), target); 1.49 + } 1.50 + 1.51 + /** 1.52 + * Gets a documentation tree path for a tree node within a subtree identified by a DocTreePath object. 1.53 + * @return null if the node is not found 1.54 + */ 1.55 + public static DocTreePath getPath(DocTreePath path, DocTree target) { 1.56 + path.getClass(); 1.57 + target.getClass(); 1.58 + 1.59 + class Result extends Error { 1.60 + static final long serialVersionUID = -5942088234594905625L; 1.61 + DocTreePath path; 1.62 + Result(DocTreePath path) { 1.63 + this.path = path; 1.64 + } 1.65 + } 1.66 + 1.67 + class PathFinder extends DocTreePathScanner<DocTreePath,DocTree> { 1.68 + public DocTreePath scan(DocTree tree, DocTree target) { 1.69 + if (tree == target) { 1.70 + throw new Result(new DocTreePath(getCurrentPath(), target)); 1.71 + } 1.72 + return super.scan(tree, target); 1.73 + } 1.74 + } 1.75 + 1.76 + if (path.getLeaf() == target) { 1.77 + return path; 1.78 + } 1.79 + 1.80 + try { 1.81 + new PathFinder().scan(path, target); 1.82 + } catch (Result result) { 1.83 + return result.path; 1.84 + } 1.85 + return null; 1.86 + } 1.87 + 1.88 + /** 1.89 + * Creates a DocTreePath for a root node. 1.90 + * 1.91 + * @param treePath the TreePath from which the root node was created. 1.92 + * @param t the DocCommentTree to create the path for. 1.93 + */ 1.94 + public DocTreePath(TreePath treePath, DocCommentTree t) { 1.95 + treePath.getClass(); 1.96 + t.getClass(); 1.97 + 1.98 + this.treePath = treePath; 1.99 + this.docComment = t; 1.100 + this.parent = null; 1.101 + this.leaf = t; 1.102 + } 1.103 + 1.104 + /** 1.105 + * Creates a DocTreePath for a child node. 1.106 + */ 1.107 + public DocTreePath(DocTreePath p, DocTree t) { 1.108 + if (t.getKind() == DocTree.Kind.DOC_COMMENT) { 1.109 + throw new IllegalArgumentException("Use DocTreePath(TreePath, DocCommentTree) to construct DocTreePath for a DocCommentTree."); 1.110 + } else { 1.111 + treePath = p.treePath; 1.112 + docComment = p.docComment; 1.113 + parent = p; 1.114 + } 1.115 + leaf = t; 1.116 + } 1.117 + 1.118 + /** 1.119 + * Get the TreePath associated with this path. 1.120 + * @return TreePath for this DocTreePath 1.121 + */ 1.122 + public TreePath getTreePath() { 1.123 + return treePath; 1.124 + } 1.125 + 1.126 + /** 1.127 + * Get the DocCommentTree associated with this path. 1.128 + * @return DocCommentTree for this DocTreePath 1.129 + */ 1.130 + public DocCommentTree getDocComment() { 1.131 + return docComment; 1.132 + } 1.133 + 1.134 + /** 1.135 + * Get the leaf node for this path. 1.136 + * @return DocTree for this DocTreePath 1.137 + */ 1.138 + public DocTree getLeaf() { 1.139 + return leaf; 1.140 + } 1.141 + 1.142 + /** 1.143 + * Get the path for the enclosing node, or null if there is no enclosing node. 1.144 + * @return DocTreePath of parent 1.145 + */ 1.146 + public DocTreePath getParentPath() { 1.147 + return parent; 1.148 + } 1.149 + 1.150 + public Iterator<DocTree> iterator() { 1.151 + return new Iterator<DocTree>() { 1.152 + public boolean hasNext() { 1.153 + return next != null; 1.154 + } 1.155 + 1.156 + public DocTree next() { 1.157 + DocTree t = next.leaf; 1.158 + next = next.parent; 1.159 + return t; 1.160 + } 1.161 + 1.162 + public void remove() { 1.163 + throw new UnsupportedOperationException(); 1.164 + } 1.165 + 1.166 + private DocTreePath next = DocTreePath.this; 1.167 + }; 1.168 + } 1.169 + 1.170 + private final TreePath treePath; 1.171 + private final DocCommentTree docComment; 1.172 + private final DocTree leaf; 1.173 + private final DocTreePath parent; 1.174 +}
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 2.2 +++ b/src/share/classes/com/sun/source/util/DocTreePathScanner.java Mon May 06 16:22:45 2013 +0200 2.3 @@ -0,0 +1,80 @@ 2.4 +/* 2.5 + * Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved. 2.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 2.7 + * 2.8 + * This code is free software; you can redistribute it and/or modify it 2.9 + * under the terms of the GNU General Public License version 2 only, as 2.10 + * published by the Free Software Foundation. Oracle designates this 2.11 + * particular file as subject to the "Classpath" exception as provided 2.12 + * by Oracle in the LICENSE file that accompanied this code. 2.13 + * 2.14 + * This code is distributed in the hope that it will be useful, but WITHOUT 2.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 2.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 2.17 + * version 2 for more details (a copy is included in the LICENSE file that 2.18 + * accompanied this code). 2.19 + * 2.20 + * You should have received a copy of the GNU General Public License version 2.21 + * 2 along with this work; if not, write to the Free Software Foundation, 2.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 2.23 + * 2.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 2.25 + * or visit www.oracle.com if you need additional information or have any 2.26 + * questions. 2.27 + */ 2.28 +package com.sun.source.util; 2.29 + 2.30 +import com.sun.source.doctree.DocTree; 2.31 + 2.32 +/** 2.33 + * A DocTreeVisitor that visits all the child tree nodes, and provides 2.34 + * support for maintaining a path for the parent nodes. 2.35 + * To visit nodes of a particular type, just override the 2.36 + * corresponding visitorXYZ method. 2.37 + * Inside your method, call super.visitXYZ to visit descendant 2.38 + * nodes. 2.39 + * 2.40 + * @since 1.8 2.41 + */ 2.42 +@jdk.Supported 2.43 +public class DocTreePathScanner<R, P> extends DocTreeScanner<R, P> { 2.44 + /** 2.45 + * Scan a tree from a position identified by a TreePath. 2.46 + */ 2.47 + public R scan(DocTreePath path, P p) { 2.48 + this.path = path; 2.49 + try { 2.50 + return path.getLeaf().accept(this, p); 2.51 + } finally { 2.52 + this.path = null; 2.53 + } 2.54 + } 2.55 + 2.56 + /** 2.57 + * Scan a single node. 2.58 + * The current path is updated for the duration of the scan. 2.59 + */ 2.60 + @Override 2.61 + public R scan(DocTree tree, P p) { 2.62 + if (tree == null) 2.63 + return null; 2.64 + 2.65 + DocTreePath prev = path; 2.66 + path = new DocTreePath(path, tree); 2.67 + try { 2.68 + return tree.accept(this, p); 2.69 + } finally { 2.70 + path = prev; 2.71 + } 2.72 + } 2.73 + 2.74 + /** 2.75 + * Get the current path for the node, as built up by the currently 2.76 + * active set of scan calls. 2.77 + */ 2.78 + public DocTreePath getCurrentPath() { 2.79 + return path; 2.80 + } 2.81 + 2.82 + private DocTreePath path; 2.83 +}
3.1 --- a/src/share/classes/com/sun/source/util/DocTrees.java Sun May 05 21:04:41 2013 -0700 3.2 +++ b/src/share/classes/com/sun/source/util/DocTrees.java Mon May 06 16:22:45 2013 +0200 3.3 @@ -67,10 +67,10 @@ 3.4 public abstract DocCommentTree getDocCommentTree(TreePath path); 3.5 3.6 /** 3.7 - * Gets the language model element referred to by a ReferenceTree that 3.8 - * appears on the declaration identified by the given path. 3.9 + * Gets the language model element referred to by the leaf node of the given 3.10 + * {@link DocTreePath}, or null if unknown. 3.11 */ 3.12 - public abstract Element getElement(TreePath path, ReferenceTree reference); 3.13 + public abstract Element getElement(DocTreePath path); 3.14 3.15 public abstract DocSourcePositions getSourcePositions(); 3.16
4.1 --- a/src/share/classes/com/sun/tools/doclint/Checker.java Sun May 05 21:04:41 2013 -0700 4.2 +++ b/src/share/classes/com/sun/tools/doclint/Checker.java Mon May 06 16:22:45 2013 +0200 4.3 @@ -42,7 +42,6 @@ 4.4 import javax.lang.model.element.ElementKind; 4.5 import javax.lang.model.element.ExecutableElement; 4.6 import javax.lang.model.element.Name; 4.7 -import javax.lang.model.element.TypeElement; 4.8 import javax.lang.model.type.TypeKind; 4.9 import javax.lang.model.type.TypeMirror; 4.10 import javax.tools.Diagnostic.Kind; 4.11 @@ -70,7 +69,8 @@ 4.12 import com.sun.source.doctree.ThrowsTree; 4.13 import com.sun.source.doctree.ValueTree; 4.14 import com.sun.source.doctree.VersionTree; 4.15 -import com.sun.source.util.DocTreeScanner; 4.16 +import com.sun.source.util.DocTreePath; 4.17 +import com.sun.source.util.DocTreePathScanner; 4.18 import com.sun.source.util.TreePath; 4.19 import com.sun.tools.doclint.HtmlTag.AttrKind; 4.20 import com.sun.tools.javac.tree.DocPretty; 4.21 @@ -85,7 +85,7 @@ 4.22 * risk. This code and its internal interfaces are subject to change 4.23 * or deletion without notice.</b></p> 4.24 */ 4.25 -public class Checker extends DocTreeScanner<Void, Void> { 4.26 +public class Checker extends DocTreePathScanner<Void, Void> { 4.27 final Env env; 4.28 4.29 Set<Element> foundParams = new HashSet<Element>(); 4.30 @@ -152,7 +152,7 @@ 4.31 foundInheritDoc = false; 4.32 foundReturn = false; 4.33 4.34 - scan(tree, (Void) null); 4.35 + scan(new DocTreePath(p, tree), null); 4.36 4.37 if (!isOverridingMethod) { 4.38 switch (env.currElement.getKind()) { 4.39 @@ -620,47 +620,36 @@ 4.40 } 4.41 4.42 @Override 4.43 + @SuppressWarnings("fallthrough") 4.44 public Void visitParam(ParamTree tree, Void ignore) { 4.45 boolean typaram = tree.isTypeParameter(); 4.46 IdentifierTree nameTree = tree.getName(); 4.47 - Element e = env.currElement; 4.48 - switch (e.getKind()) { 4.49 - case METHOD: case CONSTRUCTOR: { 4.50 - ExecutableElement ee = (ExecutableElement) e; 4.51 - checkParamDeclared(nameTree, typaram ? ee.getTypeParameters() : ee.getParameters()); 4.52 - break; 4.53 + Element paramElement = nameTree != null ? env.trees.getElement(new DocTreePath(getCurrentPath(), nameTree)) : null; 4.54 + 4.55 + if (paramElement == null) { 4.56 + switch (env.currElement.getKind()) { 4.57 + case CLASS: case INTERFACE: { 4.58 + if (!typaram) { 4.59 + env.messages.error(REFERENCE, tree, "dc.invalid.param"); 4.60 + break; 4.61 + } 4.62 + } 4.63 + case METHOD: case CONSTRUCTOR: { 4.64 + env.messages.error(REFERENCE, nameTree, "dc.param.name.not.found"); 4.65 + break; 4.66 + } 4.67 + 4.68 + default: 4.69 + env.messages.error(REFERENCE, tree, "dc.invalid.param"); 4.70 + break; 4.71 } 4.72 + } else { 4.73 + foundParams.add(paramElement); 4.74 + } 4.75 4.76 - case CLASS: case INTERFACE: { 4.77 - TypeElement te = (TypeElement) e; 4.78 - if (typaram) { 4.79 - checkParamDeclared(nameTree, te.getTypeParameters()); 4.80 - } else { 4.81 - env.messages.error(REFERENCE, tree, "dc.invalid.param"); 4.82 - } 4.83 - break; 4.84 - } 4.85 - 4.86 - default: 4.87 - env.messages.error(REFERENCE, tree, "dc.invalid.param"); 4.88 - break; 4.89 - } 4.90 warnIfEmpty(tree, tree.getDescription()); 4.91 return super.visitParam(tree, ignore); 4.92 } 4.93 - // where 4.94 - private void checkParamDeclared(IdentifierTree nameTree, List<? extends Element> list) { 4.95 - Name name = nameTree.getName(); 4.96 - boolean found = false; 4.97 - for (Element e: list) { 4.98 - if (name.equals(e.getSimpleName())) { 4.99 - foundParams.add(e); 4.100 - found = true; 4.101 - } 4.102 - } 4.103 - if (!found) 4.104 - env.messages.error(REFERENCE, nameTree, "dc.param.name.not.found"); 4.105 - } 4.106 4.107 private void checkParamsDocumented(List<? extends Element> list) { 4.108 if (foundInheritDoc) 4.109 @@ -678,7 +667,7 @@ 4.110 4.111 @Override 4.112 public Void visitReference(ReferenceTree tree, Void ignore) { 4.113 - Element e = env.trees.getElement(env.currPath, tree); 4.114 + Element e = env.trees.getElement(getCurrentPath()); 4.115 if (e == null) 4.116 env.messages.error(REFERENCE, tree, "dc.ref.not.found"); 4.117 return super.visitReference(tree, ignore); 4.118 @@ -716,7 +705,7 @@ 4.119 @Override 4.120 public Void visitThrows(ThrowsTree tree, Void ignore) { 4.121 ReferenceTree exName = tree.getExceptionName(); 4.122 - Element ex = env.trees.getElement(env.currPath, exName); 4.123 + Element ex = env.trees.getElement(new DocTreePath(getCurrentPath(), exName)); 4.124 if (ex == null) { 4.125 env.messages.error(REFERENCE, tree, "dc.ref.not.found"); 4.126 } else if (ex.asType().getKind() == TypeKind.DECLARED
5.1 --- a/src/share/classes/com/sun/tools/javac/api/JavacTrees.java Sun May 05 21:04:41 2013 -0700 5.2 +++ b/src/share/classes/com/sun/tools/javac/api/JavacTrees.java Mon May 06 16:22:45 2013 +0200 5.3 @@ -33,6 +33,7 @@ 5.4 import javax.lang.model.element.AnnotationMirror; 5.5 import javax.lang.model.element.AnnotationValue; 5.6 import javax.lang.model.element.Element; 5.7 +import javax.lang.model.element.ElementKind; 5.8 import javax.lang.model.element.ExecutableElement; 5.9 import javax.lang.model.element.TypeElement; 5.10 import javax.lang.model.type.DeclaredType; 5.11 @@ -44,12 +45,12 @@ 5.12 5.13 import com.sun.source.doctree.DocCommentTree; 5.14 import com.sun.source.doctree.DocTree; 5.15 -import com.sun.source.doctree.ReferenceTree; 5.16 import com.sun.source.tree.CatchTree; 5.17 import com.sun.source.tree.CompilationUnitTree; 5.18 import com.sun.source.tree.Scope; 5.19 import com.sun.source.tree.Tree; 5.20 import com.sun.source.util.DocSourcePositions; 5.21 +import com.sun.source.util.DocTreePath; 5.22 import com.sun.source.util.DocTreeScanner; 5.23 import com.sun.source.util.DocTrees; 5.24 import com.sun.source.util.JavacTask; 5.25 @@ -314,7 +315,7 @@ 5.26 return TreePath.getPath(treeTopLevel.snd, treeTopLevel.fst); 5.27 } 5.28 5.29 - public Element getElement(TreePath path) { 5.30 + public Symbol getElement(TreePath path) { 5.31 JCTree tree = (JCTree) path.getLeaf(); 5.32 Symbol sym = TreeInfo.symbolFor(tree); 5.33 if (sym == null) { 5.34 @@ -343,11 +344,19 @@ 5.35 } 5.36 5.37 @Override 5.38 - public Element getElement(TreePath path, ReferenceTree reference) { 5.39 - if (!(reference instanceof DCReference)) 5.40 - return null; 5.41 - DCReference ref = (DCReference) reference; 5.42 + public Element getElement(DocTreePath path) { 5.43 + DocTree forTree = path.getLeaf(); 5.44 + if (forTree instanceof DCReference) 5.45 + return attributeDocReference(path.getTreePath(), ((DCReference) forTree)); 5.46 + if (forTree instanceof DCIdentifier) { 5.47 + if (path.getParentPath().getLeaf() instanceof DCParam) { 5.48 + return attributeParamIdentifier(path.getTreePath(), (DCParam) path.getParentPath().getLeaf()); 5.49 + } 5.50 + } 5.51 + return null; 5.52 + } 5.53 5.54 + private Symbol attributeDocReference(TreePath path, DCReference ref) { 5.55 Env<AttrContext> env = getAttrContext(path); 5.56 5.57 Log.DeferredDiagnosticHandler deferredDiagnosticHandler = 5.58 @@ -427,6 +436,30 @@ 5.59 } 5.60 } 5.61 5.62 + private Symbol attributeParamIdentifier(TreePath path, DCParam ptag) { 5.63 + Symbol javadocSymbol = getElement(path); 5.64 + if (javadocSymbol == null) 5.65 + return null; 5.66 + ElementKind kind = javadocSymbol.getKind(); 5.67 + List<? extends Symbol> params = List.nil(); 5.68 + if (kind == ElementKind.METHOD || kind == ElementKind.CONSTRUCTOR) { 5.69 + MethodSymbol ee = (MethodSymbol) javadocSymbol; 5.70 + params = ptag.isTypeParameter() 5.71 + ? ee.getTypeParameters() 5.72 + : ee.getParameters(); 5.73 + } else if (kind.isClass() || kind.isInterface()) { 5.74 + ClassSymbol te = (ClassSymbol) javadocSymbol; 5.75 + params = te.getTypeParameters(); 5.76 + } 5.77 + 5.78 + for (Symbol param : params) { 5.79 + if (param.getSimpleName() == ptag.getName().getName()) { 5.80 + return param; 5.81 + } 5.82 + } 5.83 + return null; 5.84 + } 5.85 + 5.86 /** @see com.sun.tools.javadoc.ClassDocImpl#findField */ 5.87 private VarSymbol findField(ClassSymbol tsym, Name fieldName) { 5.88 return searchField(tsym, fieldName, new HashSet<ClassSymbol>());
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 6.2 +++ b/test/tools/javac/doctree/DocTreePathScannerTest.java Mon May 06 16:22:45 2013 +0200 6.3 @@ -0,0 +1,161 @@ 6.4 +/* 6.5 + * Copyright (c) 2013, 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 + * @test 6.29 + * @bug 8009724 6.30 + * @summary adding DocTreePath and DocTreePathScanner 6.31 + */ 6.32 + 6.33 +import com.sun.source.doctree.DocCommentTree; 6.34 +import com.sun.source.doctree.DocTree; 6.35 +import com.sun.source.doctree.DocTree.Kind; 6.36 +import com.sun.source.doctree.DocTreeVisitor; 6.37 +import com.sun.source.tree.ClassTree; 6.38 +import com.sun.source.tree.CompilationUnitTree; 6.39 +import com.sun.source.tree.MethodTree; 6.40 +import com.sun.source.tree.Tree; 6.41 +import com.sun.source.tree.VariableTree; 6.42 +import com.sun.source.util.DocTreePath; 6.43 +import com.sun.source.util.DocTreePathScanner; 6.44 +import com.sun.source.util.DocTreeScanner; 6.45 +import com.sun.source.util.DocTrees; 6.46 +import com.sun.source.util.JavacTask; 6.47 +import com.sun.source.util.TreePath; 6.48 +import com.sun.source.util.TreePathScanner; 6.49 +import com.sun.tools.javac.api.JavacTool; 6.50 +import java.io.File; 6.51 +import java.util.ArrayList; 6.52 +import java.util.List; 6.53 +import javax.lang.model.element.Name; 6.54 +import javax.tools.JavaFileObject; 6.55 +import javax.tools.StandardJavaFileManager; 6.56 + 6.57 +public class DocTreePathScannerTest { 6.58 + public static void main(String... args) throws Exception { 6.59 + DocTreePathScannerTest t = new DocTreePathScannerTest(); 6.60 + t.run(); 6.61 + } 6.62 + 6.63 + void run() throws Exception { 6.64 + List<File> files = new ArrayList<File>(); 6.65 + File testSrc = new File(System.getProperty("test.src")); 6.66 + for (File f: testSrc.listFiles()) { 6.67 + if (f.isFile() && f.getName().endsWith(".java")) 6.68 + files.add(f); 6.69 + } 6.70 + 6.71 + JavacTool javac = JavacTool.create(); 6.72 + StandardJavaFileManager fm = javac.getStandardFileManager(null, null, null); 6.73 + 6.74 + Iterable<? extends JavaFileObject> fos = fm.getJavaFileObjectsFromFiles(files); 6.75 + 6.76 + JavacTask t = javac.getTask(null, fm, null, null, null, fos); 6.77 + DocTrees trees = DocTrees.instance(t); 6.78 + 6.79 + Iterable<? extends CompilationUnitTree> units = t.parse(); 6.80 + 6.81 + DeclScanner ds = new DeclScanner(trees); 6.82 + for (CompilationUnitTree unit: units) { 6.83 + ds.scan(unit, null); 6.84 + } 6.85 + 6.86 + if (errors > 0) 6.87 + throw new Exception(errors + " errors occurred"); 6.88 + } 6.89 + 6.90 + void error(String msg) { 6.91 + System.err.println("Error: " + msg); 6.92 + errors++; 6.93 + } 6.94 + 6.95 + int errors; 6.96 + 6.97 + class DeclScanner extends TreePathScanner<Void, Void> { 6.98 + DocTrees trees; 6.99 + DocTreePathScanner<Void,Void> cs; 6.100 + 6.101 + DeclScanner(DocTrees trees) { 6.102 + this.trees = trees; 6.103 + cs = new CommentPathScanner(); 6.104 + } 6.105 + 6.106 + @Override 6.107 + public Void visitClass(ClassTree tree, Void ignore) { 6.108 + super.visitClass(tree, ignore); 6.109 + visitDecl(tree, tree.getSimpleName()); 6.110 + return null; 6.111 + } 6.112 + 6.113 + @Override 6.114 + public Void visitMethod(MethodTree tree, Void ignore) { 6.115 + super.visitMethod(tree, ignore); 6.116 + visitDecl(tree, tree.getName()); 6.117 + return null; 6.118 + } 6.119 + 6.120 + @Override 6.121 + public Void visitVariable(VariableTree tree, Void ignore) { 6.122 + super.visitVariable(tree, ignore); 6.123 + visitDecl(tree, tree.getName()); 6.124 + return null; 6.125 + } 6.126 + 6.127 + void visitDecl(Tree tree, Name name) { 6.128 + TreePath path = getCurrentPath(); 6.129 + DocCommentTree dc = trees.getDocCommentTree(path); 6.130 + if (dc != null) 6.131 + cs.scan(new DocTreePath(path, dc), null); 6.132 + } 6.133 + } 6.134 + 6.135 + class CommentPathScanner extends DocTreePathScanner<Void, Void> { 6.136 + CommentPathScanner() {} 6.137 + 6.138 + @Override 6.139 + public Void scan(final DocTree tree, Void ignore) { 6.140 + if (tree != null) { 6.141 + DocTree previous = null; 6.142 + for (DocTree current : getCurrentPath()) { 6.143 + if (previous != null) { 6.144 + final List<DocTree> children = new ArrayList<>(); 6.145 + current.accept(new DocTreeScanner<Void, Void>() { 6.146 + @Override public Void scan(DocTree node, Void p) { 6.147 + children.add(node); 6.148 + return null; 6.149 + } 6.150 + }, null); 6.151 + 6.152 + if (!children.contains(previous)) { 6.153 + error("Invalid DocTreePath for: " + tree); 6.154 + } 6.155 + } 6.156 + 6.157 + previous = current; 6.158 + } 6.159 + } 6.160 + return super.scan(tree, ignore); 6.161 + } 6.162 + } 6.163 + 6.164 +}
7.1 --- a/test/tools/javac/doctree/ReferenceTest.java Sun May 05 21:04:41 2013 -0700 7.2 +++ b/test/tools/javac/doctree/ReferenceTest.java Mon May 06 16:22:45 2013 +0200 7.3 @@ -1,5 +1,5 @@ 7.4 /* 7.5 - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. 7.6 + * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. 7.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 7.8 * 7.9 * This code is free software; you can redistribute it and/or modify it 7.10 @@ -36,6 +36,8 @@ 7.11 import com.sun.source.doctree.ReferenceTree; 7.12 import com.sun.source.doctree.SeeTree; 7.13 import com.sun.source.doctree.TextTree; 7.14 +import com.sun.source.util.DocTreePath; 7.15 +import com.sun.source.util.DocTreePathScanner; 7.16 import com.sun.source.util.DocTreeScanner; 7.17 import com.sun.source.util.DocTrees; 7.18 import com.sun.source.util.TreePath; 7.19 @@ -125,7 +127,7 @@ 7.20 return true; 7.21 } 7.22 7.23 - class DocCommentScanner extends DocTreeScanner<Void, Void> { 7.24 + class DocCommentScanner extends DocTreePathScanner<Void, Void> { 7.25 TreePath path; 7.26 DocCommentTree dc; 7.27 7.28 @@ -135,7 +137,7 @@ 7.29 7.30 void scan() { 7.31 dc = trees.getDocCommentTree(path); 7.32 - scan(dc, null); 7.33 + scan(new DocTreePath(path, dc), null); 7.34 } 7.35 7.36 @Override 7.37 @@ -158,7 +160,7 @@ 7.38 void checkReference(ReferenceTree tree, List<? extends DocTree> label) { 7.39 String sig = tree.getSignature(); 7.40 7.41 - Element found = trees.getElement(path, tree); 7.42 + Element found = trees.getElement(new DocTreePath(getCurrentPath(), tree)); 7.43 if (found == null) { 7.44 System.err.println(sig + " NOT FOUND"); 7.45 } else {