001 /* 002 * Copyright 2006 Sun Microsystems, Inc. All Rights Reserved. 003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 004 * 005 * This code is free software; you can redistribute it and/or modify it 006 * under the terms of the GNU General Public License version 2 only, as 007 * published by the Free Software Foundation. Sun designates this 008 * particular file as subject to the "Classpath" exception as provided 009 * by Sun in the LICENSE file that accompanied this code. 010 * 011 * This code is distributed in the hope that it will be useful, but WITHOUT 012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 014 * version 2 for more details (a copy is included in the LICENSE file that 015 * accompanied this code). 016 * 017 * You should have received a copy of the GNU General Public License version 018 * 2 along with this work; if not, write to the Free Software Foundation, 019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 020 * 021 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 022 * CA 95054 USA or visit www.sun.com if you need additional information or 023 * have any questions. 024 */ 025 026 package com.sun.source.util; 027 028 import com.sun.source.tree.*; 029 import java.util.Iterator; 030 031 /** 032 * A path of tree nodes, typically used to represent the sequence of ancestor 033 * nodes of a tree node up to the top level CompilationUnitTree node. 034 * 035 * @author Jonathan Gibbons 036 * @since 1.6 037 */ 038 public class TreePath implements Iterable<Tree> { 039 /** 040 * Gets a tree path for a tree node within a compilation unit. 041 * @return null if the node is not found 042 */ 043 public static TreePath getPath(CompilationUnitTree unit, Tree target) { 044 return getPath(new TreePath(unit), target); 045 } 046 047 /** 048 * Gets a tree path for a tree node within a subtree identified by a TreePath object. 049 * @return null if the node is not found 050 */ 051 public static TreePath getPath(TreePath path, Tree target) { 052 path.getClass(); 053 target.getClass(); 054 055 class Result extends Error { 056 static final long serialVersionUID = -5942088234594905625L; 057 TreePath path; 058 Result(TreePath path) { 059 this.path = path; 060 } 061 } 062 class PathFinder extends TreePathScanner<TreePath,Tree> { 063 public TreePath scan(Tree tree, Tree target) { 064 if (tree == target) 065 throw new Result(new TreePath(getCurrentPath(), target)); 066 return super.scan(tree, target); 067 } 068 } 069 070 try { 071 new PathFinder().scan(path, target); 072 } catch (Result result) { 073 return result.path; 074 } 075 return null; 076 } 077 078 /** 079 * Creates a TreePath for a root node. 080 */ 081 public TreePath(CompilationUnitTree t) { 082 this(null, t); 083 } 084 085 /** 086 * Creates a TreePath for a child node. 087 */ 088 public TreePath(TreePath p, Tree t) { 089 if (t.getKind() == Tree.Kind.COMPILATION_UNIT) { 090 compilationUnit = (CompilationUnitTree) t; 091 parent = null; 092 } 093 else { 094 compilationUnit = p.compilationUnit; 095 parent = p; 096 } 097 leaf = t; 098 } 099 /** 100 * Get the compilation unit associated with this path. 101 */ 102 public CompilationUnitTree getCompilationUnit() { 103 return compilationUnit; 104 } 105 106 /** 107 * Get the leaf node for this path. 108 */ 109 public Tree getLeaf() { 110 return leaf; 111 } 112 113 /** 114 * Get the path for the enclosing node, or null if there is no enclosing node. 115 */ 116 public TreePath getParentPath() { 117 return parent; 118 } 119 120 public Iterator<Tree> iterator() { 121 return new Iterator<Tree>() { 122 public boolean hasNext() { 123 return curr.parent != null; 124 } 125 126 public Tree next() { 127 curr = curr.parent; 128 return curr.leaf; 129 } 130 131 public void remove() { 132 throw new UnsupportedOperationException(); 133 } 134 135 private TreePath curr; 136 }; 137 } 138 139 private CompilationUnitTree compilationUnit; 140 private Tree leaf; 141 private TreePath parent; 142 }