1 19 package org.netbeans.modules.ruby; 20 21 import java.util.ArrayList ; 22 import java.util.Collections ; 23 import java.util.Iterator ; 24 import java.util.List ; 25 import java.util.ListIterator ; 26 import org.jruby.ast.Node; 27 import org.jruby.lexer.yacc.ISourcePosition; 28 29 30 35 public class AstPath implements Iterable <Node> { 36 private ArrayList <Node> path = new ArrayList <Node>(30); 37 38 public AstPath() { 39 } 40 41 public AstPath(ArrayList <Node> path) { 42 this.path = path; 43 } 44 45 public void descend(Node node) { 46 path.add(node); 47 } 48 49 public void ascend() { 50 path.remove(path.size()-1); 51 } 52 53 56 public AstPath(Node root, int caretOffset) { 57 findPathTo(root, caretOffset); 58 } 59 60 63 @SuppressWarnings ("unchecked") 64 public AstPath(Node node, Node target) { 65 if (!find(node, target)) { 66 path.clear(); 67 } else { 68 Collections.reverse(path); 71 } 72 } 73 74 78 @SuppressWarnings ("unchecked") 79 public Node findPathTo(Node node, int offset) { 80 Node result = find(node, offset); 81 path.add(node); 82 83 Collections.reverse(path); 86 87 return result; 88 } 89 90 @SuppressWarnings ("unchecked") 91 private Node find(Node node, int offset) { 92 ISourcePosition pos = node.getPosition(); 93 int begin = pos.getStartOffset(); 94 int end = pos.getEndOffset(); 95 96 if ((offset >= begin) && (offset <= end)) { 97 List <Node> children = (List <Node>)node.childNodes(); 98 99 for (Node child : children) { 100 Node found = find(child, offset); 101 102 if (found != null) { 103 path.add(child); 104 105 return found; 106 } 107 } 108 109 return node; 110 } else { 111 List <Node> children = (List <Node>)node.childNodes(); 112 113 for (Node child : children) { 114 Node found = find(child, offset); 115 116 if (found != null) { 117 path.add(child); 118 119 return found; 120 } 121 } 122 123 return null; 124 } 125 } 126 127 130 @SuppressWarnings ("unchecked") 131 public boolean find(Node node, Node target) { 132 if (node == target) { 133 return true; 134 } 135 136 List <Node> children = (List <Node>)node.childNodes(); 137 138 for (Node child : children) { 139 boolean found = find(child, target); 140 141 if (found) { 142 path.add(child); 143 144 return found; 145 } 146 } 147 148 return false; 149 } 150 151 @Override 152 public String toString() { 153 StringBuilder sb = new StringBuilder (); 154 sb.append("Path("); 155 sb.append(path.size()); 156 sb.append(")=["); 157 for (Node n : path) { 158 String name = n.getClass().getName(); 159 name = name.substring(name.lastIndexOf('.')+1); 160 sb.append(name); 161 sb.append(":"); 162 } 163 sb.append("]"); 164 return sb.toString(); 165 } 166 167 public Node leaf() { 168 if (path.size() == 0) { 169 return null; 170 } else { 171 return path.get(path.size()-1); 172 } 173 } 174 175 public Node leafParent() { 176 if (path.size() < 2) { 177 return null; 178 } else { 179 return path.get(path.size()-2); 180 } 181 } 182 183 public Node leafGrandParent() { 184 if (path.size() < 3) { 185 return null; 186 } else { 187 return path.get(path.size()-3); 188 } 189 } 190 191 192 public Node root() { 193 if (path.size() == 0) { 194 return null; 195 } else { 196 return path.get(0); 197 } 198 } 199 200 201 public Iterator <Node> iterator() { 202 return new LeafToRootIterator(); 203 } 204 205 206 public ListIterator <Node> rootToLeaf() { 207 return path.listIterator(); 208 } 209 210 211 public ListIterator <Node> leafToRoot() { 212 return new LeafToRootIterator(); 213 } 214 215 private class LeafToRootIterator implements ListIterator <Node> { 216 private ListIterator <Node> it; 217 218 private LeafToRootIterator() { 219 it = path.listIterator(path.size()); 220 } 221 222 public boolean hasNext() { 223 return it.hasPrevious(); 224 } 225 226 public Node next() { 227 return it.previous(); 228 } 229 230 public boolean hasPrevious() { 231 return it.hasNext(); 232 } 233 234 public Node previous() { 235 return it.next(); 236 } 237 238 public int nextIndex() { 239 return it.previousIndex(); 240 } 241 242 public int previousIndex() { 243 return it.nextIndex(); 244 } 245 246 public void remove() { 247 throw new UnsupportedOperationException ("Not supported yet."); 248 } 249 250 public void set(Node arg0) { 251 throw new UnsupportedOperationException ("Not supported yet."); 252 } 253 254 public void add(Node arg0) { 255 throw new UnsupportedOperationException ("Not supported yet."); 256 } 257 } 258 } 259 | Popular Tags |