1 /* 2 * Copyright (c) 2006, 2013, 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 26 package com.sun.source.util; 27 28 import com.sun.source.doctree.DocCommentTree; 29 import com.sun.source.doctree.DocTree; 30 import java.util.Iterator; 31 32 /** 33 * A path of tree nodes, typically used to represent the sequence of ancestor 34 * nodes of a tree node up to the top level DocCommentTree node. 35 * 36 * @since 1.8 37 */ 38 @jdk.Supported 39 public class DocTreePath implements Iterable<DocTree> { 40 /** 41 * Gets a documentation tree path for a tree node within a compilation unit. 42 * @return null if the node is not found 43 */ 44 public static DocTreePath getPath(TreePath treePath, DocCommentTree doc, DocTree target) { 45 return getPath(new DocTreePath(treePath, doc), target); 46 } 47 48 /** 49 * Gets a documentation tree path for a tree node within a subtree identified by a DocTreePath object. 50 * @return null if the node is not found 51 */ 52 public static DocTreePath getPath(DocTreePath path, DocTree target) { 53 path.getClass(); 54 target.getClass(); 55 56 class Result extends Error { 57 static final long serialVersionUID = -5942088234594905625L; 58 DocTreePath path; 59 Result(DocTreePath path) { 60 this.path = path; 61 } 62 } 63 64 class PathFinder extends DocTreePathScanner<DocTreePath,DocTree> { 65 public DocTreePath scan(DocTree tree, DocTree target) { 66 if (tree == target) { 67 throw new Result(new DocTreePath(getCurrentPath(), target)); 68 } 69 return super.scan(tree, target); 70 } 71 } 72 73 if (path.getLeaf() == target) { 74 return path; 75 } 76 77 try { 78 new PathFinder().scan(path, target); 79 } catch (Result result) { 80 return result.path; 81 } 82 return null; 83 } 84 85 /** 86 * Creates a DocTreePath for a root node. 87 * 88 * @param treePath the TreePath from which the root node was created. 89 * @param t the DocCommentTree to create the path for. 90 */ 91 public DocTreePath(TreePath treePath, DocCommentTree t) { 92 treePath.getClass(); 93 t.getClass(); 94 95 this.treePath = treePath; 96 this.docComment = t; 97 this.parent = null; 98 this.leaf = t; 99 } 100 101 /** 102 * Creates a DocTreePath for a child node. 103 */ 104 public DocTreePath(DocTreePath p, DocTree t) { 105 if (t.getKind() == DocTree.Kind.DOC_COMMENT) { 106 throw new IllegalArgumentException("Use DocTreePath(TreePath, DocCommentTree) to construct DocTreePath for a DocCommentTree."); 107 } else { 108 treePath = p.treePath; 109 docComment = p.docComment; 110 parent = p; 111 } 112 leaf = t; 113 } 114 115 /** 116 * Get the TreePath associated with this path. 117 * @return TreePath for this DocTreePath 118 */ 119 public TreePath getTreePath() { 120 return treePath; 121 } 122 123 /** 124 * Get the DocCommentTree associated with this path. 125 * @return DocCommentTree for this DocTreePath 126 */ 127 public DocCommentTree getDocComment() { 128 return docComment; 129 } 130 131 /** 132 * Get the leaf node for this path. 133 * @return DocTree for this DocTreePath 134 */ 135 public DocTree getLeaf() { 136 return leaf; 137 } 138 139 /** 140 * Get the path for the enclosing node, or null if there is no enclosing node. 141 * @return DocTreePath of parent 142 */ 143 public DocTreePath getParentPath() { 144 return parent; 145 } 146 147 public Iterator<DocTree> iterator() { 148 return new Iterator<DocTree>() { 149 public boolean hasNext() { 150 return next != null; 151 } 152 153 public DocTree next() { 154 DocTree t = next.leaf; 155 next = next.parent; 156 return t; 157 } 158 159 public void remove() { 160 throw new UnsupportedOperationException(); 161 } 162 163 private DocTreePath next = DocTreePath.this; 164 }; 165 } 166 167 private final TreePath treePath; 168 private final DocCommentTree docComment; 169 private final DocTree leaf; 170 private final DocTreePath parent; 171 }