8009724: Enhance the DocTree API with DocTreePath

Mon, 06 May 2013 16:22:45 +0200

author
jlahoda
date
Mon, 06 May 2013 16:22:45 +0200
changeset 1726
a7ff36d06fa2
parent 1725
e8987ce7fb4b
child 1727
68142e69cafb

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>

src/share/classes/com/sun/source/util/DocTreePath.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/source/util/DocTreePathScanner.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/source/util/DocTrees.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/doclint/Checker.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/javac/api/JavacTrees.java file | annotate | diff | comparison | revisions
test/tools/javac/doctree/DocTreePathScannerTest.java file | annotate | diff | comparison | revisions
test/tools/javac/doctree/ReferenceTest.java file | annotate | diff | comparison | revisions
     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 {

mercurial