DocTreePath.java revision 3896:8e4dbcb99277
1/* 2 * Copyright (c) 2006, 2016, 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. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26package com.sun.source.util; 27 28import com.sun.source.doctree.DocCommentTree; 29import com.sun.source.doctree.DocTree; 30 31import java.util.Iterator; 32import java.util.Objects; 33 34/** 35 * A path of tree nodes, typically used to represent the sequence of ancestor 36 * nodes of a tree node up to the top level DocCommentTree node. 37 * 38 * @since 1.8 39 */ 40public class DocTreePath implements Iterable<DocTree> { 41 /** 42 * Returns a documentation tree path for a tree node within a compilation unit, 43 * or {@code null} if the node is not found. 44 * @param treePath the path for the node with which the doc comment is associated 45 * @param doc the doc comment associated with the node 46 * @param target a node within the doc comment 47 * @return a path identifying the target within the tree 48 */ 49 public static DocTreePath getPath(TreePath treePath, DocCommentTree doc, DocTree target) { 50 return getPath(new DocTreePath(treePath, doc), target); 51 } 52 53 /** 54 * Returns a documentation tree path for a tree node within a subtree 55 * identified by a DocTreePath object, or {@code null} if the node is not found. 56 * @param path a path identifying a node within a doc comment tree 57 * @param target a node to be located within the given node 58 * @return a path identifying the target node 59 */ 60 public static DocTreePath getPath(DocTreePath path, DocTree target) { 61 Objects.requireNonNull(path); //null check 62 Objects.requireNonNull(target); //null check 63 64 class Result extends Error { 65 static final long serialVersionUID = -5942088234594905625L; 66 DocTreePath path; 67 Result(DocTreePath path) { 68 this.path = path; 69 } 70 } 71 72 class PathFinder extends DocTreePathScanner<DocTreePath,DocTree> { 73 @Override 74 public DocTreePath scan(DocTree tree, DocTree target) { 75 if (tree == target) { 76 throw new Result(new DocTreePath(getCurrentPath(), target)); 77 } 78 return super.scan(tree, target); 79 } 80 } 81 82 if (path.getLeaf() == target) { 83 return path; 84 } 85 86 try { 87 new PathFinder().scan(path, target); 88 } catch (Result result) { 89 return result.path; 90 } 91 return null; 92 } 93 94 /** 95 * Creates a DocTreePath for a root node. 96 * 97 * @param treePath the TreePath from which the root node was created. 98 * @param t the DocCommentTree to create the path for. 99 */ 100 public DocTreePath(TreePath treePath, DocCommentTree t) { 101 this.treePath = treePath; 102 this.docComment = Objects.requireNonNull(t); 103 this.parent = null; 104 this.leaf = t; 105 } 106 107 /** 108 * Creates a DocTreePath for a child node. 109 * @param p the parent node 110 * @param t the child node 111 */ 112 public DocTreePath(DocTreePath p, DocTree t) { 113 if (t.getKind() == DocTree.Kind.DOC_COMMENT) { 114 throw new IllegalArgumentException("Use DocTreePath(TreePath, DocCommentTree) to construct DocTreePath for a DocCommentTree."); 115 } else { 116 treePath = p.treePath; 117 docComment = p.docComment; 118 parent = p; 119 } 120 leaf = t; 121 } 122 123 /** 124 * Returns the TreePath associated with this path. 125 * @return the TreePath for this DocTreePath 126 */ 127 public TreePath getTreePath() { 128 return treePath; 129 } 130 131 /** 132 * Returns the DocCommentTree associated with this path. 133 * @return the DocCommentTree for this DocTreePath 134 */ 135 public DocCommentTree getDocComment() { 136 return docComment; 137 } 138 139 /** 140 * Returns the leaf node for this path. 141 * @return the DocTree for this DocTreePath 142 */ 143 public DocTree getLeaf() { 144 return leaf; 145 } 146 147 /** 148 * Returns the path for the enclosing node, or {@code null} if there is no enclosing node. 149 * @return DocTreePath of parent 150 */ 151 public DocTreePath getParentPath() { 152 return parent; 153 } 154 155 @Override 156 public Iterator<DocTree> iterator() { 157 return new Iterator<DocTree>() { 158 @Override 159 public boolean hasNext() { 160 return next != null; 161 } 162 163 @Override 164 public DocTree next() { 165 DocTree t = next.leaf; 166 next = next.parent; 167 return t; 168 } 169 170 @Override 171 public void remove() { 172 throw new UnsupportedOperationException(); 173 } 174 175 private DocTreePath next = DocTreePath.this; 176 }; 177 } 178 179 private final TreePath treePath; 180 private final DocCommentTree docComment; 181 private final DocTree leaf; 182 private final DocTreePath parent; 183} 184