mirror of
https://github.com/openjdk/jdk.git
synced 2026-05-11 22:19:43 +00:00
8009724: Enhance the DocTree API with DocTreePath
Adding DocTreePath and DocTreePathScanner similar to TreePath and TreePathScanner, respectively Co-authored-by: Ralph Benjamin Ruijs <ralphbenjamin@netbeans.org> Reviewed-by: jjg
This commit is contained in:
parent
d606b9d0d6
commit
57d8a7fc0f
171
langtools/src/share/classes/com/sun/source/util/DocTreePath.java
Normal file
171
langtools/src/share/classes/com/sun/source/util/DocTreePath.java
Normal file
@ -0,0 +1,171 @@
|
||||
/*
|
||||
* Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.source.util;
|
||||
|
||||
import com.sun.source.doctree.DocCommentTree;
|
||||
import com.sun.source.doctree.DocTree;
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* A path of tree nodes, typically used to represent the sequence of ancestor
|
||||
* nodes of a tree node up to the top level DocCommentTree node.
|
||||
*
|
||||
* @since 1.8
|
||||
*/
|
||||
@jdk.Supported
|
||||
public class DocTreePath implements Iterable<DocTree> {
|
||||
/**
|
||||
* Gets a documentation tree path for a tree node within a compilation unit.
|
||||
* @return null if the node is not found
|
||||
*/
|
||||
public static DocTreePath getPath(TreePath treePath, DocCommentTree doc, DocTree target) {
|
||||
return getPath(new DocTreePath(treePath, doc), target);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a documentation tree path for a tree node within a subtree identified by a DocTreePath object.
|
||||
* @return null if the node is not found
|
||||
*/
|
||||
public static DocTreePath getPath(DocTreePath path, DocTree target) {
|
||||
path.getClass();
|
||||
target.getClass();
|
||||
|
||||
class Result extends Error {
|
||||
static final long serialVersionUID = -5942088234594905625L;
|
||||
DocTreePath path;
|
||||
Result(DocTreePath path) {
|
||||
this.path = path;
|
||||
}
|
||||
}
|
||||
|
||||
class PathFinder extends DocTreePathScanner<DocTreePath,DocTree> {
|
||||
public DocTreePath scan(DocTree tree, DocTree target) {
|
||||
if (tree == target) {
|
||||
throw new Result(new DocTreePath(getCurrentPath(), target));
|
||||
}
|
||||
return super.scan(tree, target);
|
||||
}
|
||||
}
|
||||
|
||||
if (path.getLeaf() == target) {
|
||||
return path;
|
||||
}
|
||||
|
||||
try {
|
||||
new PathFinder().scan(path, target);
|
||||
} catch (Result result) {
|
||||
return result.path;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a DocTreePath for a root node.
|
||||
*
|
||||
* @param treePath the TreePath from which the root node was created.
|
||||
* @param t the DocCommentTree to create the path for.
|
||||
*/
|
||||
public DocTreePath(TreePath treePath, DocCommentTree t) {
|
||||
treePath.getClass();
|
||||
t.getClass();
|
||||
|
||||
this.treePath = treePath;
|
||||
this.docComment = t;
|
||||
this.parent = null;
|
||||
this.leaf = t;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a DocTreePath for a child node.
|
||||
*/
|
||||
public DocTreePath(DocTreePath p, DocTree t) {
|
||||
if (t.getKind() == DocTree.Kind.DOC_COMMENT) {
|
||||
throw new IllegalArgumentException("Use DocTreePath(TreePath, DocCommentTree) to construct DocTreePath for a DocCommentTree.");
|
||||
} else {
|
||||
treePath = p.treePath;
|
||||
docComment = p.docComment;
|
||||
parent = p;
|
||||
}
|
||||
leaf = t;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the TreePath associated with this path.
|
||||
* @return TreePath for this DocTreePath
|
||||
*/
|
||||
public TreePath getTreePath() {
|
||||
return treePath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the DocCommentTree associated with this path.
|
||||
* @return DocCommentTree for this DocTreePath
|
||||
*/
|
||||
public DocCommentTree getDocComment() {
|
||||
return docComment;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the leaf node for this path.
|
||||
* @return DocTree for this DocTreePath
|
||||
*/
|
||||
public DocTree getLeaf() {
|
||||
return leaf;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the path for the enclosing node, or null if there is no enclosing node.
|
||||
* @return DocTreePath of parent
|
||||
*/
|
||||
public DocTreePath getParentPath() {
|
||||
return parent;
|
||||
}
|
||||
|
||||
public Iterator<DocTree> iterator() {
|
||||
return new Iterator<DocTree>() {
|
||||
public boolean hasNext() {
|
||||
return next != null;
|
||||
}
|
||||
|
||||
public DocTree next() {
|
||||
DocTree t = next.leaf;
|
||||
next = next.parent;
|
||||
return t;
|
||||
}
|
||||
|
||||
public void remove() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
private DocTreePath next = DocTreePath.this;
|
||||
};
|
||||
}
|
||||
|
||||
private final TreePath treePath;
|
||||
private final DocCommentTree docComment;
|
||||
private final DocTree leaf;
|
||||
private final DocTreePath parent;
|
||||
}
|
||||
@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package com.sun.source.util;
|
||||
|
||||
import com.sun.source.doctree.DocTree;
|
||||
|
||||
/**
|
||||
* A DocTreeVisitor that visits all the child tree nodes, and provides
|
||||
* support for maintaining a path for the parent nodes.
|
||||
* To visit nodes of a particular type, just override the
|
||||
* corresponding visitorXYZ method.
|
||||
* Inside your method, call super.visitXYZ to visit descendant
|
||||
* nodes.
|
||||
*
|
||||
* @since 1.8
|
||||
*/
|
||||
@jdk.Supported
|
||||
public class DocTreePathScanner<R, P> extends DocTreeScanner<R, P> {
|
||||
/**
|
||||
* Scan a tree from a position identified by a TreePath.
|
||||
*/
|
||||
public R scan(DocTreePath path, P p) {
|
||||
this.path = path;
|
||||
try {
|
||||
return path.getLeaf().accept(this, p);
|
||||
} finally {
|
||||
this.path = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Scan a single node.
|
||||
* The current path is updated for the duration of the scan.
|
||||
*/
|
||||
@Override
|
||||
public R scan(DocTree tree, P p) {
|
||||
if (tree == null)
|
||||
return null;
|
||||
|
||||
DocTreePath prev = path;
|
||||
path = new DocTreePath(path, tree);
|
||||
try {
|
||||
return tree.accept(this, p);
|
||||
} finally {
|
||||
path = prev;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current path for the node, as built up by the currently
|
||||
* active set of scan calls.
|
||||
*/
|
||||
public DocTreePath getCurrentPath() {
|
||||
return path;
|
||||
}
|
||||
|
||||
private DocTreePath path;
|
||||
}
|
||||
@ -67,10 +67,10 @@ public abstract class DocTrees extends Trees {
|
||||
public abstract DocCommentTree getDocCommentTree(TreePath path);
|
||||
|
||||
/**
|
||||
* Gets the language model element referred to by a ReferenceTree that
|
||||
* appears on the declaration identified by the given path.
|
||||
* Gets the language model element referred to by the leaf node of the given
|
||||
* {@link DocTreePath}, or null if unknown.
|
||||
*/
|
||||
public abstract Element getElement(TreePath path, ReferenceTree reference);
|
||||
public abstract Element getElement(DocTreePath path);
|
||||
|
||||
public abstract DocSourcePositions getSourcePositions();
|
||||
|
||||
|
||||
@ -42,7 +42,6 @@ import javax.lang.model.element.Element;
|
||||
import javax.lang.model.element.ElementKind;
|
||||
import javax.lang.model.element.ExecutableElement;
|
||||
import javax.lang.model.element.Name;
|
||||
import javax.lang.model.element.TypeElement;
|
||||
import javax.lang.model.type.TypeKind;
|
||||
import javax.lang.model.type.TypeMirror;
|
||||
import javax.tools.Diagnostic.Kind;
|
||||
@ -70,7 +69,8 @@ import com.sun.source.doctree.TextTree;
|
||||
import com.sun.source.doctree.ThrowsTree;
|
||||
import com.sun.source.doctree.ValueTree;
|
||||
import com.sun.source.doctree.VersionTree;
|
||||
import com.sun.source.util.DocTreeScanner;
|
||||
import com.sun.source.util.DocTreePath;
|
||||
import com.sun.source.util.DocTreePathScanner;
|
||||
import com.sun.source.util.TreePath;
|
||||
import com.sun.tools.doclint.HtmlTag.AttrKind;
|
||||
import com.sun.tools.javac.tree.DocPretty;
|
||||
@ -85,7 +85,7 @@ import static com.sun.tools.doclint.Messages.Group.*;
|
||||
* risk. This code and its internal interfaces are subject to change
|
||||
* or deletion without notice.</b></p>
|
||||
*/
|
||||
public class Checker extends DocTreeScanner<Void, Void> {
|
||||
public class Checker extends DocTreePathScanner<Void, Void> {
|
||||
final Env env;
|
||||
|
||||
Set<Element> foundParams = new HashSet<Element>();
|
||||
@ -152,7 +152,7 @@ public class Checker extends DocTreeScanner<Void, Void> {
|
||||
foundInheritDoc = false;
|
||||
foundReturn = false;
|
||||
|
||||
scan(tree, (Void) null);
|
||||
scan(new DocTreePath(p, tree), null);
|
||||
|
||||
if (!isOverridingMethod) {
|
||||
switch (env.currElement.getKind()) {
|
||||
@ -620,47 +620,36 @@ public class Checker extends DocTreeScanner<Void, Void> {
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("fallthrough")
|
||||
public Void visitParam(ParamTree tree, Void ignore) {
|
||||
boolean typaram = tree.isTypeParameter();
|
||||
IdentifierTree nameTree = tree.getName();
|
||||
Element e = env.currElement;
|
||||
switch (e.getKind()) {
|
||||
case METHOD: case CONSTRUCTOR: {
|
||||
ExecutableElement ee = (ExecutableElement) e;
|
||||
checkParamDeclared(nameTree, typaram ? ee.getTypeParameters() : ee.getParameters());
|
||||
break;
|
||||
}
|
||||
Element paramElement = nameTree != null ? env.trees.getElement(new DocTreePath(getCurrentPath(), nameTree)) : null;
|
||||
|
||||
case CLASS: case INTERFACE: {
|
||||
TypeElement te = (TypeElement) e;
|
||||
if (typaram) {
|
||||
checkParamDeclared(nameTree, te.getTypeParameters());
|
||||
} else {
|
||||
env.messages.error(REFERENCE, tree, "dc.invalid.param");
|
||||
if (paramElement == null) {
|
||||
switch (env.currElement.getKind()) {
|
||||
case CLASS: case INTERFACE: {
|
||||
if (!typaram) {
|
||||
env.messages.error(REFERENCE, tree, "dc.invalid.param");
|
||||
break;
|
||||
}
|
||||
}
|
||||
case METHOD: case CONSTRUCTOR: {
|
||||
env.messages.error(REFERENCE, nameTree, "dc.param.name.not.found");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
env.messages.error(REFERENCE, tree, "dc.invalid.param");
|
||||
break;
|
||||
default:
|
||||
env.messages.error(REFERENCE, tree, "dc.invalid.param");
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
foundParams.add(paramElement);
|
||||
}
|
||||
|
||||
warnIfEmpty(tree, tree.getDescription());
|
||||
return super.visitParam(tree, ignore);
|
||||
}
|
||||
// where
|
||||
private void checkParamDeclared(IdentifierTree nameTree, List<? extends Element> list) {
|
||||
Name name = nameTree.getName();
|
||||
boolean found = false;
|
||||
for (Element e: list) {
|
||||
if (name.equals(e.getSimpleName())) {
|
||||
foundParams.add(e);
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
env.messages.error(REFERENCE, nameTree, "dc.param.name.not.found");
|
||||
}
|
||||
|
||||
private void checkParamsDocumented(List<? extends Element> list) {
|
||||
if (foundInheritDoc)
|
||||
@ -678,7 +667,7 @@ public class Checker extends DocTreeScanner<Void, Void> {
|
||||
|
||||
@Override
|
||||
public Void visitReference(ReferenceTree tree, Void ignore) {
|
||||
Element e = env.trees.getElement(env.currPath, tree);
|
||||
Element e = env.trees.getElement(getCurrentPath());
|
||||
if (e == null)
|
||||
env.messages.error(REFERENCE, tree, "dc.ref.not.found");
|
||||
return super.visitReference(tree, ignore);
|
||||
@ -716,7 +705,7 @@ public class Checker extends DocTreeScanner<Void, Void> {
|
||||
@Override
|
||||
public Void visitThrows(ThrowsTree tree, Void ignore) {
|
||||
ReferenceTree exName = tree.getExceptionName();
|
||||
Element ex = env.trees.getElement(env.currPath, exName);
|
||||
Element ex = env.trees.getElement(new DocTreePath(getCurrentPath(), exName));
|
||||
if (ex == null) {
|
||||
env.messages.error(REFERENCE, tree, "dc.ref.not.found");
|
||||
} else if (ex.asType().getKind() == TypeKind.DECLARED
|
||||
|
||||
@ -33,6 +33,7 @@ import javax.annotation.processing.ProcessingEnvironment;
|
||||
import javax.lang.model.element.AnnotationMirror;
|
||||
import javax.lang.model.element.AnnotationValue;
|
||||
import javax.lang.model.element.Element;
|
||||
import javax.lang.model.element.ElementKind;
|
||||
import javax.lang.model.element.ExecutableElement;
|
||||
import javax.lang.model.element.TypeElement;
|
||||
import javax.lang.model.type.DeclaredType;
|
||||
@ -44,12 +45,12 @@ import javax.tools.JavaFileObject;
|
||||
|
||||
import com.sun.source.doctree.DocCommentTree;
|
||||
import com.sun.source.doctree.DocTree;
|
||||
import com.sun.source.doctree.ReferenceTree;
|
||||
import com.sun.source.tree.CatchTree;
|
||||
import com.sun.source.tree.CompilationUnitTree;
|
||||
import com.sun.source.tree.Scope;
|
||||
import com.sun.source.tree.Tree;
|
||||
import com.sun.source.util.DocSourcePositions;
|
||||
import com.sun.source.util.DocTreePath;
|
||||
import com.sun.source.util.DocTreeScanner;
|
||||
import com.sun.source.util.DocTrees;
|
||||
import com.sun.source.util.JavacTask;
|
||||
@ -314,7 +315,7 @@ public class JavacTrees extends DocTrees {
|
||||
return TreePath.getPath(treeTopLevel.snd, treeTopLevel.fst);
|
||||
}
|
||||
|
||||
public Element getElement(TreePath path) {
|
||||
public Symbol getElement(TreePath path) {
|
||||
JCTree tree = (JCTree) path.getLeaf();
|
||||
Symbol sym = TreeInfo.symbolFor(tree);
|
||||
if (sym == null) {
|
||||
@ -343,11 +344,19 @@ public class JavacTrees extends DocTrees {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Element getElement(TreePath path, ReferenceTree reference) {
|
||||
if (!(reference instanceof DCReference))
|
||||
return null;
|
||||
DCReference ref = (DCReference) reference;
|
||||
public Element getElement(DocTreePath path) {
|
||||
DocTree forTree = path.getLeaf();
|
||||
if (forTree instanceof DCReference)
|
||||
return attributeDocReference(path.getTreePath(), ((DCReference) forTree));
|
||||
if (forTree instanceof DCIdentifier) {
|
||||
if (path.getParentPath().getLeaf() instanceof DCParam) {
|
||||
return attributeParamIdentifier(path.getTreePath(), (DCParam) path.getParentPath().getLeaf());
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private Symbol attributeDocReference(TreePath path, DCReference ref) {
|
||||
Env<AttrContext> env = getAttrContext(path);
|
||||
|
||||
Log.DeferredDiagnosticHandler deferredDiagnosticHandler =
|
||||
@ -427,6 +436,30 @@ public class JavacTrees extends DocTrees {
|
||||
}
|
||||
}
|
||||
|
||||
private Symbol attributeParamIdentifier(TreePath path, DCParam ptag) {
|
||||
Symbol javadocSymbol = getElement(path);
|
||||
if (javadocSymbol == null)
|
||||
return null;
|
||||
ElementKind kind = javadocSymbol.getKind();
|
||||
List<? extends Symbol> params = List.nil();
|
||||
if (kind == ElementKind.METHOD || kind == ElementKind.CONSTRUCTOR) {
|
||||
MethodSymbol ee = (MethodSymbol) javadocSymbol;
|
||||
params = ptag.isTypeParameter()
|
||||
? ee.getTypeParameters()
|
||||
: ee.getParameters();
|
||||
} else if (kind.isClass() || kind.isInterface()) {
|
||||
ClassSymbol te = (ClassSymbol) javadocSymbol;
|
||||
params = te.getTypeParameters();
|
||||
}
|
||||
|
||||
for (Symbol param : params) {
|
||||
if (param.getSimpleName() == ptag.getName().getName()) {
|
||||
return param;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/** @see com.sun.tools.javadoc.ClassDocImpl#findField */
|
||||
private VarSymbol findField(ClassSymbol tsym, Name fieldName) {
|
||||
return searchField(tsym, fieldName, new HashSet<ClassSymbol>());
|
||||
|
||||
161
langtools/test/tools/javac/doctree/DocTreePathScannerTest.java
Normal file
161
langtools/test/tools/javac/doctree/DocTreePathScannerTest.java
Normal file
@ -0,0 +1,161 @@
|
||||
/*
|
||||
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8009724
|
||||
* @summary adding DocTreePath and DocTreePathScanner
|
||||
*/
|
||||
|
||||
import com.sun.source.doctree.DocCommentTree;
|
||||
import com.sun.source.doctree.DocTree;
|
||||
import com.sun.source.doctree.DocTree.Kind;
|
||||
import com.sun.source.doctree.DocTreeVisitor;
|
||||
import com.sun.source.tree.ClassTree;
|
||||
import com.sun.source.tree.CompilationUnitTree;
|
||||
import com.sun.source.tree.MethodTree;
|
||||
import com.sun.source.tree.Tree;
|
||||
import com.sun.source.tree.VariableTree;
|
||||
import com.sun.source.util.DocTreePath;
|
||||
import com.sun.source.util.DocTreePathScanner;
|
||||
import com.sun.source.util.DocTreeScanner;
|
||||
import com.sun.source.util.DocTrees;
|
||||
import com.sun.source.util.JavacTask;
|
||||
import com.sun.source.util.TreePath;
|
||||
import com.sun.source.util.TreePathScanner;
|
||||
import com.sun.tools.javac.api.JavacTool;
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javax.lang.model.element.Name;
|
||||
import javax.tools.JavaFileObject;
|
||||
import javax.tools.StandardJavaFileManager;
|
||||
|
||||
public class DocTreePathScannerTest {
|
||||
public static void main(String... args) throws Exception {
|
||||
DocTreePathScannerTest t = new DocTreePathScannerTest();
|
||||
t.run();
|
||||
}
|
||||
|
||||
void run() throws Exception {
|
||||
List<File> files = new ArrayList<File>();
|
||||
File testSrc = new File(System.getProperty("test.src"));
|
||||
for (File f: testSrc.listFiles()) {
|
||||
if (f.isFile() && f.getName().endsWith(".java"))
|
||||
files.add(f);
|
||||
}
|
||||
|
||||
JavacTool javac = JavacTool.create();
|
||||
StandardJavaFileManager fm = javac.getStandardFileManager(null, null, null);
|
||||
|
||||
Iterable<? extends JavaFileObject> fos = fm.getJavaFileObjectsFromFiles(files);
|
||||
|
||||
JavacTask t = javac.getTask(null, fm, null, null, null, fos);
|
||||
DocTrees trees = DocTrees.instance(t);
|
||||
|
||||
Iterable<? extends CompilationUnitTree> units = t.parse();
|
||||
|
||||
DeclScanner ds = new DeclScanner(trees);
|
||||
for (CompilationUnitTree unit: units) {
|
||||
ds.scan(unit, null);
|
||||
}
|
||||
|
||||
if (errors > 0)
|
||||
throw new Exception(errors + " errors occurred");
|
||||
}
|
||||
|
||||
void error(String msg) {
|
||||
System.err.println("Error: " + msg);
|
||||
errors++;
|
||||
}
|
||||
|
||||
int errors;
|
||||
|
||||
class DeclScanner extends TreePathScanner<Void, Void> {
|
||||
DocTrees trees;
|
||||
DocTreePathScanner<Void,Void> cs;
|
||||
|
||||
DeclScanner(DocTrees trees) {
|
||||
this.trees = trees;
|
||||
cs = new CommentPathScanner();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitClass(ClassTree tree, Void ignore) {
|
||||
super.visitClass(tree, ignore);
|
||||
visitDecl(tree, tree.getSimpleName());
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitMethod(MethodTree tree, Void ignore) {
|
||||
super.visitMethod(tree, ignore);
|
||||
visitDecl(tree, tree.getName());
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitVariable(VariableTree tree, Void ignore) {
|
||||
super.visitVariable(tree, ignore);
|
||||
visitDecl(tree, tree.getName());
|
||||
return null;
|
||||
}
|
||||
|
||||
void visitDecl(Tree tree, Name name) {
|
||||
TreePath path = getCurrentPath();
|
||||
DocCommentTree dc = trees.getDocCommentTree(path);
|
||||
if (dc != null)
|
||||
cs.scan(new DocTreePath(path, dc), null);
|
||||
}
|
||||
}
|
||||
|
||||
class CommentPathScanner extends DocTreePathScanner<Void, Void> {
|
||||
CommentPathScanner() {}
|
||||
|
||||
@Override
|
||||
public Void scan(final DocTree tree, Void ignore) {
|
||||
if (tree != null) {
|
||||
DocTree previous = null;
|
||||
for (DocTree current : getCurrentPath()) {
|
||||
if (previous != null) {
|
||||
final List<DocTree> children = new ArrayList<>();
|
||||
current.accept(new DocTreeScanner<Void, Void>() {
|
||||
@Override public Void scan(DocTree node, Void p) {
|
||||
children.add(node);
|
||||
return null;
|
||||
}
|
||||
}, null);
|
||||
|
||||
if (!children.contains(previous)) {
|
||||
error("Invalid DocTreePath for: " + tree);
|
||||
}
|
||||
}
|
||||
|
||||
previous = current;
|
||||
}
|
||||
}
|
||||
return super.scan(tree, ignore);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -36,6 +36,8 @@ import com.sun.source.doctree.LinkTree;
|
||||
import com.sun.source.doctree.ReferenceTree;
|
||||
import com.sun.source.doctree.SeeTree;
|
||||
import com.sun.source.doctree.TextTree;
|
||||
import com.sun.source.util.DocTreePath;
|
||||
import com.sun.source.util.DocTreePathScanner;
|
||||
import com.sun.source.util.DocTreeScanner;
|
||||
import com.sun.source.util.DocTrees;
|
||||
import com.sun.source.util.TreePath;
|
||||
@ -125,7 +127,7 @@ public class ReferenceTest extends AbstractProcessor {
|
||||
return true;
|
||||
}
|
||||
|
||||
class DocCommentScanner extends DocTreeScanner<Void, Void> {
|
||||
class DocCommentScanner extends DocTreePathScanner<Void, Void> {
|
||||
TreePath path;
|
||||
DocCommentTree dc;
|
||||
|
||||
@ -135,7 +137,7 @@ public class ReferenceTest extends AbstractProcessor {
|
||||
|
||||
void scan() {
|
||||
dc = trees.getDocCommentTree(path);
|
||||
scan(dc, null);
|
||||
scan(new DocTreePath(path, dc), null);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -158,7 +160,7 @@ public class ReferenceTest extends AbstractProcessor {
|
||||
void checkReference(ReferenceTree tree, List<? extends DocTree> label) {
|
||||
String sig = tree.getSignature();
|
||||
|
||||
Element found = trees.getElement(path, tree);
|
||||
Element found = trees.getElement(new DocTreePath(getCurrentPath(), tree));
|
||||
if (found == null) {
|
||||
System.err.println(sig + " NOT FOUND");
|
||||
} else {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user