1 19 package org.netbeans.modules.ruby; 20 21 import java.util.ArrayList ; 22 import java.util.HashMap ; 23 import java.util.List ; 24 import java.util.Map ; 25 26 import org.jruby.ast.AliasNode; 27 import org.jruby.ast.ArgsNode; 28 import org.jruby.ast.ArgumentNode; 29 import org.jruby.ast.CallNode; 30 import org.jruby.ast.ClassVarDeclNode; 31 import org.jruby.ast.ClassVarNode; 32 import org.jruby.ast.Colon2Node; 33 import org.jruby.ast.ConstDeclNode; 34 import org.jruby.ast.ConstNode; 35 import org.jruby.ast.DAsgnNode; 36 import org.jruby.ast.DVarNode; 37 import org.jruby.ast.DefnNode; 38 import org.jruby.ast.DefsNode; 39 import org.jruby.ast.FCallNode; 40 import org.jruby.ast.GlobalAsgnNode; 41 import org.jruby.ast.GlobalVarNode; 42 import org.jruby.ast.InstAsgnNode; 43 import org.jruby.ast.InstVarNode; 44 import org.jruby.ast.ListNode; 45 import org.jruby.ast.LocalAsgnNode; 46 import org.jruby.ast.LocalVarNode; 47 import org.jruby.ast.Node; 48 import org.jruby.ast.SymbolNode; 49 import org.jruby.ast.VCallNode; 50 import org.jruby.ast.types.INameNode; 51 import org.netbeans.api.gsf.OffsetRange; 52 import org.netbeans.api.gsf.ColoringAttributes; 53 import org.netbeans.api.gsf.CompilationInfo; 54 55 56 67 public class OccurrencesFinder implements org.netbeans.api.gsf.OccurrencesFinder { 68 private boolean cancelled; 69 private int caretPosition; 70 private Map <OffsetRange, ColoringAttributes> occurrences; 71 72 73 private boolean ignoreAlias; 74 75 public OccurrencesFinder() { 76 } 77 78 public Map <OffsetRange, ColoringAttributes> getOccurrences() { 79 return occurrences; 80 } 81 82 protected final synchronized boolean isCancelled() { 83 return cancelled; 84 } 85 86 protected final synchronized void resume() { 87 cancelled = false; 88 } 89 90 public final synchronized void cancel() { 91 cancelled = true; 92 } 93 94 public void run(CompilationInfo info) { 95 resume(); 96 97 if (isCancelled()) { 98 return; 99 } 100 101 Node root = AstUtilities.getRoot(info); 102 103 if (root == null) { 104 return; 105 } 106 107 Map <OffsetRange, ColoringAttributes> highlights = 108 new HashMap <OffsetRange, ColoringAttributes>(100); 109 110 AstPath path = new AstPath(root, caretPosition); 111 Node closest = path.leaf(); 112 113 if (closest != null) { 114 if (closest instanceof LocalVarNode || closest instanceof LocalAsgnNode) { 115 String name = ((INameNode)closest).getName(); 117 Node method = AstUtilities.findLocalScope(closest, path); 118 119 highlightLocal(method, name, highlights); 120 } else if (closest instanceof DAsgnNode) { 121 String name = ((INameNode)closest).getName(); 123 Node block = AstUtilities.findLocalScope(closest, path); 124 125 highlightDynamnic(block, name, highlights); 126 } else if (closest instanceof DVarNode) { 127 String name = ((DVarNode)closest).getName(); Node block = AstUtilities.findLocalScope(closest, path); 130 131 highlightDynamnic(block, name, highlights); 132 } else if (closest instanceof InstAsgnNode) { 133 String name = ((INameNode)closest).getName(); 135 highlightInstance(root, name, highlights); 136 } else if (closest instanceof InstVarNode) { 137 highlightInstance(root, ((INameNode)closest).getName(), highlights); 139 } else if (closest instanceof ClassVarDeclNode) { 140 String name = ((INameNode)closest).getName(); 142 highlightClassVar(root, name, highlights); 143 } else if (closest instanceof ClassVarNode) { 144 highlightClassVar(root, ((ClassVarNode)closest).getName(), highlights); 146 } else if (closest instanceof GlobalVarNode) { 147 String name = ((GlobalVarNode)closest).getName(); highlightGlobal(root, name, highlights); 150 } else if (closest instanceof GlobalAsgnNode) { 151 String name = ((INameNode)closest).getName(); 153 highlightGlobal(root, name, highlights); 154 } else if (closest instanceof FCallNode || closest instanceof VCallNode || 155 closest instanceof CallNode) { 156 String name = ((INameNode)closest).getName(); 158 159 if (!name.equals("[]")) { 162 highlightMethod(root, name, Arity.getCallArity(closest), highlights); 163 } 164 } else if (closest instanceof DefnNode) { 165 OffsetRange range = AstUtilities.getFunctionNameRange(root); 169 170 if (range.containsInclusive(caretPosition)) { 171 String name = ((DefnNode)closest).getName(); 172 highlightMethod(root, name, Arity.getDefArity(closest), highlights); 173 } 174 } else if (closest instanceof DefsNode) { 175 String name = ((DefsNode)closest).getName(); 177 highlightMethod(root, name, Arity.getDefArity(closest), highlights); 178 } else if (closest instanceof Colon2Node) { 179 highlights.put(AstUtilities.getRange(closest), ColoringAttributes.MARK_OCCURRENCES); 181 182 highlightClass(root, ((INameNode)closest).getName(), highlights); 183 184 } else if (closest instanceof ConstNode || closest instanceof ConstDeclNode) { 186 highlightClass(root, ((INameNode)closest).getName(), highlights); 189 } else if (closest instanceof SymbolNode) { 190 191 String name = ((INameNode)closest).getName(); 193 highlightInstance(root, "@" + name, highlights); 194 highlightClassVar(root, "@@" + name, highlights); 195 highlightMethod(root, name, Arity.UNKNOWN, highlights); 196 highlightClass(root, name, highlights); 197 } else if (closest instanceof AliasNode) { 198 AliasNode an = (AliasNode)closest; 199 200 String newName = an.getNewName(); 202 203 int newLength = newName.length(); 211 int aliasPos = an.getPosition().getStartOffset(); 212 String name = null; 213 214 if (caretPosition > (aliasPos + 1)) { 218 if (caretPosition > (aliasPos + 6 + newLength)) { 219 OffsetRange range = AstUtilities.getAliasOldRange(an); 220 highlights.put(range, ColoringAttributes.MARK_OCCURRENCES); 221 name = an.getOldName(); 222 } else { 223 OffsetRange range = AstUtilities.getAliasNewRange(an); 224 highlights.put(range, ColoringAttributes.MARK_OCCURRENCES); 225 name = an.getNewName(); 226 } 227 } 228 229 if (name != null) { 230 int count = highlights.size(); 235 Node method = AstUtilities.findLocalScope(closest, path); 236 237 ignoreAlias = true; 240 241 try { 242 highlightLocal(method, name, highlights); 243 244 if (highlights.size() == count) { 245 Node block = AstUtilities.findLocalScope(closest, path); 247 248 highlightDynamnic(block, name, highlights); 249 250 if (highlights.size() == count) { 251 highlightMethod(root, name, Arity.UNKNOWN, highlights); 253 254 if (highlights.size() == count) { 255 highlightInstance(root, name, highlights); 257 258 if (highlights.size() == count) { 259 highlightGlobal(root, name, highlights); 261 262 if (highlights.size() == count) { 263 highlightClass(root, name, highlights); 265 266 if (highlights.size() == count) { 267 highlightClassVar(root, name, highlights); 269 } 270 } 271 } 272 } 273 } 274 } 275 } finally { 276 ignoreAlias = false; 277 } 278 } 279 } else if (closest instanceof ArgumentNode) { 280 String name = ((ArgumentNode)closest).getName(); 283 Node parent = path.leafParent(); 284 if (parent != null) { 285 if (parent instanceof DefnNode || parent instanceof DefsNode) { 286 highlightMethod(root, name, Arity.getDefArity(parent), highlights); 287 } else { 288 Node method = AstUtilities.findLocalScope(closest, path); 290 291 highlightLocal(method, name, highlights); 292 } 293 } 294 } 295 } 296 297 if (isCancelled()) { 298 return; 299 } 300 301 if (highlights.size() > 0) { 302 this.occurrences = highlights; 303 } else { 304 this.occurrences = null; 305 } 306 } 307 308 @SuppressWarnings ("unchecked") 309 private void highlightLocal(Node node, String name, 310 Map <OffsetRange, ColoringAttributes> highlights) { 311 if (node instanceof LocalVarNode) { 312 if (((INameNode)node).getName().equals(name)) { 313 OffsetRange range = AstUtilities.getRange(node); 314 highlights.put(range, ColoringAttributes.MARK_OCCURRENCES); 315 } 316 } else if (node instanceof LocalAsgnNode) { 317 if (((INameNode)node).getName().equals(name)) { 318 OffsetRange range = AstUtilities.getRange(node); 319 range = new OffsetRange(range.getStart(), range.getStart() + name.length()); 321 highlights.put(range, ColoringAttributes.MARK_OCCURRENCES); 322 } 323 } else if (node instanceof ArgsNode) { 324 ArgsNode an = (ArgsNode)node; 325 326 if (an.getArgsCount() > 0) { 327 List <Node> args = (List <Node>)an.childNodes(); 328 329 for (Node arg : args) { 330 if (arg instanceof ListNode) { 331 List <Node> args2 = (List <Node>)arg.childNodes(); 332 333 for (Node arg2 : args2) { 334 if (arg2 instanceof ArgumentNode) { 335 if (((ArgumentNode)arg2).getName().equals(name)) { 336 OffsetRange range = AstUtilities.getRange(arg2); 337 highlights.put(range, ColoringAttributes.MARK_OCCURRENCES); 338 } 339 } else if (arg2 instanceof LocalAsgnNode) { 340 if (((LocalAsgnNode)arg2).getName().equals(name)) { 341 OffsetRange range = AstUtilities.getRange(arg2); 342 highlights.put(range, ColoringAttributes.MARK_OCCURRENCES); 343 } 344 } 345 } 346 } 347 } 348 } 349 } else if (!ignoreAlias && node instanceof AliasNode) { 350 AliasNode an = (AliasNode)node; 351 352 if (an.getNewName().equals(name)) { 353 OffsetRange range = AstUtilities.getAliasNewRange(an); 354 highlights.put(range, ColoringAttributes.MARK_OCCURRENCES); 355 } else if (an.getOldName().equals(name)) { 356 OffsetRange range = AstUtilities.getAliasOldRange(an); 357 highlights.put(range, ColoringAttributes.MARK_OCCURRENCES); 358 } 359 } 360 361 List <Node> list = node.childNodes(); 362 363 for (Node child : list) { 364 highlightLocal(child, name, highlights); 365 } 366 } 367 368 @SuppressWarnings ("unchecked") 369 private void highlightDynamnic(Node node, String name, 370 Map <OffsetRange, ColoringAttributes> highlights) { 371 if (node instanceof DVarNode) { 372 if (((DVarNode)node).getName().equals(name)) { 374 OffsetRange range = AstUtilities.getRange(node); 375 highlights.put(range, ColoringAttributes.MARK_OCCURRENCES); 376 } 377 } else if (node instanceof DAsgnNode) { 378 if (((INameNode)node).getName().equals(name)) { 379 OffsetRange range = AstUtilities.getRange(node); 380 range = new OffsetRange(range.getStart(), range.getStart() + name.length()); 382 highlights.put(range, ColoringAttributes.MARK_OCCURRENCES); 383 } 384 385 } else if (!ignoreAlias && node instanceof AliasNode) { 410 AliasNode an = (AliasNode)node; 411 412 if (an.getNewName().equals(name)) { 413 OffsetRange range = AstUtilities.getAliasNewRange(an); 414 highlights.put(range, ColoringAttributes.MARK_OCCURRENCES); 415 } else if (an.getOldName().equals(name)) { 416 OffsetRange range = AstUtilities.getAliasOldRange(an); 417 highlights.put(range, ColoringAttributes.MARK_OCCURRENCES); 418 } 419 } 420 421 List <Node> list = node.childNodes(); 422 423 for (Node child : list) { 424 highlightDynamnic(child, name, highlights); 425 } 426 } 427 428 @SuppressWarnings ("unchecked") 429 private void highlightInstance(Node node, String name, 430 Map <OffsetRange, ColoringAttributes> highlights) { 431 if (node instanceof InstVarNode) { 432 if (((INameNode)node).getName().equals(name)) { 433 OffsetRange range = AstUtilities.getRange(node); 434 highlights.put(range, ColoringAttributes.MARK_OCCURRENCES); 435 } 436 } else if (node instanceof InstAsgnNode) { 437 if (((INameNode)node).getName().equals(name)) { 438 OffsetRange range = AstUtilities.getRange(node); 439 range = new OffsetRange(range.getStart(), range.getStart() + name.length()); 441 highlights.put(range, ColoringAttributes.MARK_OCCURRENCES); 442 } 443 } else if (!ignoreAlias && node instanceof AliasNode) { 444 AliasNode an = (AliasNode)node; 445 446 if (an.getNewName().equals(name)) { 447 OffsetRange range = AstUtilities.getAliasNewRange(an); 448 highlights.put(range, ColoringAttributes.MARK_OCCURRENCES); 449 } else if (an.getOldName().equals(name)) { 450 OffsetRange range = AstUtilities.getAliasOldRange(an); 451 highlights.put(range, ColoringAttributes.MARK_OCCURRENCES); 452 } 453 } else if (AstUtilities.isAttr(node)) { 454 SymbolNode[] symbols = AstUtilities.getAttrSymbols(node); 457 458 for (int i = 0; i < symbols.length; i++) { 459 if (name.equals("@" + symbols[i].getName())) { 460 OffsetRange range = AstUtilities.getRange(symbols[i]); 461 highlights.put(range, ColoringAttributes.MARK_OCCURRENCES); 462 } 463 } 464 } 465 466 List <Node> list = node.childNodes(); 467 468 for (Node child : list) { 469 highlightInstance(child, name, highlights); 470 } 471 } 472 473 @SuppressWarnings ("unchecked") 474 private void highlightClassVar(Node node, String name, 475 Map <OffsetRange, ColoringAttributes> highlights) { 476 if (node instanceof ClassVarNode) { 477 if (((ClassVarNode)node).getName().equals(name)) { 478 OffsetRange range = AstUtilities.getRange(node); 479 highlights.put(range, ColoringAttributes.MARK_OCCURRENCES); 480 } 481 } else if (node instanceof ClassVarDeclNode) { 482 if (((INameNode)node).getName().equals(name)) { 483 OffsetRange range = AstUtilities.getRange(node); 484 range = new OffsetRange(range.getStart(), range.getStart() + name.length()); 486 highlights.put(range, ColoringAttributes.MARK_OCCURRENCES); 487 } 488 } else if (!ignoreAlias && node instanceof AliasNode) { 489 AliasNode an = (AliasNode)node; 490 491 if (an.getNewName().equals(name)) { 492 OffsetRange range = AstUtilities.getAliasNewRange(an); 493 highlights.put(range, ColoringAttributes.MARK_OCCURRENCES); 494 } else if (an.getOldName().equals(name)) { 495 OffsetRange range = AstUtilities.getAliasOldRange(an); 496 highlights.put(range, ColoringAttributes.MARK_OCCURRENCES); 497 } 498 499 } 512 513 List <Node> list = node.childNodes(); 514 515 for (Node child : list) { 516 highlightClassVar(child, name, highlights); 517 } 518 } 519 520 @SuppressWarnings ("unchecked") 521 private void highlightGlobal(Node node, String name, 522 Map <OffsetRange, ColoringAttributes> highlights) { 523 if (node instanceof GlobalVarNode) { 524 if (((GlobalVarNode)node).getName().equals(name)) { 526 OffsetRange range = AstUtilities.getRange(node); 527 highlights.put(range, ColoringAttributes.MARK_OCCURRENCES); 528 } 529 } else if (node instanceof GlobalAsgnNode) { 530 if (((INameNode)node).getName().equals(name)) { 531 OffsetRange range = AstUtilities.getRange(node); 532 range = new OffsetRange(range.getStart(), range.getStart() + name.length()); 534 highlights.put(range, ColoringAttributes.MARK_OCCURRENCES); 535 } 536 } else if (!ignoreAlias && node instanceof AliasNode) { 537 AliasNode an = (AliasNode)node; 538 539 if (an.getNewName().equals(name)) { 540 OffsetRange range = AstUtilities.getAliasNewRange(an); 541 highlights.put(range, ColoringAttributes.MARK_OCCURRENCES); 542 } else if (an.getOldName().equals(name)) { 543 OffsetRange range = AstUtilities.getAliasOldRange(an); 544 highlights.put(range, ColoringAttributes.MARK_OCCURRENCES); 545 } 546 } 547 548 List <Node> list = node.childNodes(); 549 550 for (Node child : list) { 551 highlightGlobal(child, name, highlights); 552 } 553 } 554 555 @SuppressWarnings ("unchecked") 556 private void highlightMethod(Node node, String name, Arity arity, 557 Map <OffsetRange, ColoringAttributes> highlights) { 558 if (node instanceof DefnNode) { 560 if (((DefnNode)node).getName().equals(name) && 562 Arity.matches(arity, Arity.getDefArity(node))) { 563 OffsetRange range = AstUtilities.getFunctionNameRange(node); 564 highlights.put(range, ColoringAttributes.MARK_OCCURRENCES); 565 } 566 } else if (node instanceof DefsNode) { 567 if (((DefsNode)node).getName().equals(name) && 569 Arity.matches(arity, Arity.getDefArity(node))) { 570 OffsetRange range = AstUtilities.getFunctionNameRange(node); 571 highlights.put(range, ColoringAttributes.MARK_OCCURRENCES); 572 } 573 } else if (node instanceof FCallNode || node instanceof CallNode || 574 node instanceof VCallNode) { 575 if (((INameNode)node).getName().equals(name) && 576 Arity.matches(Arity.getCallArity(node), arity)) { 577 OffsetRange range = AstUtilities.getCallRange(node); 578 highlights.put(range, ColoringAttributes.MARK_OCCURRENCES); 579 } 580 } else if (!ignoreAlias && node instanceof AliasNode) { 581 AliasNode an = (AliasNode)node; 582 583 if (an.getNewName().equals(name)) { 584 OffsetRange range = AstUtilities.getAliasNewRange(an); 585 highlights.put(range, ColoringAttributes.MARK_OCCURRENCES); 586 } else if (an.getOldName().equals(name)) { 587 OffsetRange range = AstUtilities.getAliasOldRange(an); 588 highlights.put(range, ColoringAttributes.MARK_OCCURRENCES); 589 } 590 } 591 592 List <Node> list = node.childNodes(); 593 594 for (Node child : list) { 595 highlightMethod(child, name, arity, highlights); 596 } 597 } 598 599 @SuppressWarnings ("unchecked") 600 private void highlightClass(Node node, String name, 601 Map <OffsetRange, ColoringAttributes> highlights) { 602 if (node instanceof ConstNode) { 603 if (((INameNode)node).getName().equals(name)) { 604 OffsetRange range = AstUtilities.getRange(node); 605 highlights.put(range, ColoringAttributes.MARK_OCCURRENCES); 606 } 607 } else if (node instanceof ConstDeclNode) { 608 if (((INameNode)node).getName().equals(name)) { 609 OffsetRange range = AstUtilities.getLValueRange((ConstDeclNode)node); 610 highlights.put(range, ColoringAttributes.MARK_OCCURRENCES); 611 } 612 } else if (node instanceof Colon2Node) { 613 if (((INameNode)node).getName().equals(name)) { 614 OffsetRange range = AstUtilities.getRange(node); 615 highlights.put(range, ColoringAttributes.MARK_OCCURRENCES); 616 } 617 } else if (!ignoreAlias && node instanceof AliasNode) { 618 AliasNode an = (AliasNode)node; 619 620 if (an.getNewName().equals(name)) { 621 OffsetRange range = AstUtilities.getAliasNewRange(an); 622 highlights.put(range, ColoringAttributes.MARK_OCCURRENCES); 623 } else if (an.getOldName().equals(name)) { 624 OffsetRange range = AstUtilities.getAliasOldRange(an); 625 highlights.put(range, ColoringAttributes.MARK_OCCURRENCES); 626 } 627 } 628 629 List <Node> list = node.childNodes(); 630 631 for (Node child : list) { 632 highlightClass(child, name, highlights); 633 } 634 } 635 636 public void setCaretPosition(int position) { 637 this.caretPosition = position; 638 } 639 } 640 | Popular Tags |