DocTreePath.java revision 3193:3b3bea483542
1/* 2 * Copyright (c) 2006, 2014, 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 public DocTreePath scan(DocTree tree, DocTree target) { 74 if (tree == target) { 75 throw new Result(new DocTreePath(getCurrentPath(), target)); 76 } 77 return super.scan(tree, target); 78 } 79 } 80 81 if (path.getLeaf() == target) { 82 return path; 83 } 84 85 try { 86 new PathFinder().scan(path, target); 87 } catch (Result result) { 88 return result.path; 89 } 90 return null; 91 } 92 93 /** 94 * Creates a DocTreePath for a root node. 95 * 96 * @param treePath the TreePath from which the root node was created. 97 * @param t the DocCommentTree to create the path for. 98 */ 99 public DocTreePath(TreePath treePath, DocCommentTree t) { 100 this.treePath = Objects.requireNonNull(treePath); 101 this.docComment = Objects.requireNonNull(t); 102 this.parent = null; 103 this.leaf = t; 104 } 105 106 /** 107 * Creates a DocTreePath for a child node. 108 * @param p the parent node 109 * @param t the child node 110 */ 111 public DocTreePath(DocTreePath p, DocTree t) { 112 if (t.getKind() == DocTree.Kind.DOC_COMMENT) { 113 throw new IllegalArgumentException("Use DocTreePath(TreePath, DocCommentTree) to construct DocTreePath for a DocCommentTree."); 114 } else { 115 treePath = p.treePath; 116 docComment = p.docComment; 117 parent = p; 118 } 119 leaf = t; 120 } 121 122 /** 123 * Returns the TreePath associated with this path. 124 * @return the TreePath for this DocTreePath 125 */ 126 public TreePath getTreePath() { 127 return treePath; 128 } 129 130 /** 131 * Returns the DocCommentTree associated with this path. 132 * @return the DocCommentTree for this DocTreePath 133 */ 134 public DocCommentTree getDocComment() { 135 return docComment; 136 } 137 138 /** 139 * Returns the leaf node for this path. 140 * @return the DocTree for this DocTreePath 141 */ 142 public DocTree getLeaf() { 143 return leaf; 144 } 145 146 /** 147 * Returns the path for the enclosing node, or {@code null} if there is no enclosing node. 148 * @return DocTreePath of parent 149 */ 150 public DocTreePath getParentPath() { 151 return parent; 152 } 153 154 public Iterator<DocTree> iterator() { 155 return new Iterator<DocTree>() { 156 public boolean hasNext() { 157 return next != null; 158 } 159 160 public DocTree next() { 161 DocTree t = next.leaf; 162 next = next.parent; 163 return t; 164 } 165 166 public void remove() { 167 throw new UnsupportedOperationException(); 168 } 169 170 private DocTreePath next = DocTreePath.this; 171 }; 172 } 173 174 private final TreePath treePath; 175 private final DocCommentTree docComment; 176 private final DocTree leaf; 177 private final DocTreePath parent; 178} 179