DocTreePath.java revision 2837:1e3266d870d6
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 */ 40@jdk.Exported 41public class DocTreePath implements Iterable<DocTree> { 42 /** 43 * Returns a documentation tree path for a tree node within a compilation unit, 44 * or {@code null} if the node is not found. 45 * @param treePath the path for the node with which the doc comment is associated 46 * @param doc the doc comment associated with the node 47 * @param target a node within the doc comment 48 * @return a path identifying the target within the tree 49 */ 50 public static DocTreePath getPath(TreePath treePath, DocCommentTree doc, DocTree target) { 51 return getPath(new DocTreePath(treePath, doc), target); 52 } 53 54 /** 55 * Returns a documentation tree path for a tree node within a subtree 56 * identified by a DocTreePath object, or {@code null} if the node is not found. 57 * @param path a path identifying a node within a doc comment tree 58 * @param target a node to be located within the given node 59 * @return a path identifying the target node 60 */ 61 public static DocTreePath getPath(DocTreePath path, DocTree target) { 62 Objects.requireNonNull(path); //null check 63 Objects.requireNonNull(target); //null check 64 65 class Result extends Error { 66 static final long serialVersionUID = -5942088234594905625L; 67 DocTreePath path; 68 Result(DocTreePath path) { 69 this.path = path; 70 } 71 } 72 73 class PathFinder extends DocTreePathScanner<DocTreePath,DocTree> { 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 = Objects.requireNonNull(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 public Iterator<DocTree> iterator() { 156 return new Iterator<DocTree>() { 157 public boolean hasNext() { 158 return next != null; 159 } 160 161 public DocTree next() { 162 DocTree t = next.leaf; 163 next = next.parent; 164 return t; 165 } 166 167 public void remove() { 168 throw new UnsupportedOperationException(); 169 } 170 171 private DocTreePath next = DocTreePath.this; 172 }; 173 } 174 175 private final TreePath treePath; 176 private final DocCommentTree docComment; 177 private final DocTree leaf; 178 private final DocTreePath parent; 179} 180