1 19 20 package org.netbeans.modules.debugger.jpda.projects; 21 22 import com.sun.source.tree.AssignmentTree; 23 import com.sun.source.tree.ExpressionStatementTree; 24 import com.sun.source.tree.ExpressionTree; 25 import com.sun.source.tree.Scope; 26 import com.sun.source.tree.VariableTree; 27 import com.sun.source.util.TreeScanner; 28 import java.awt.Color ; 29 import java.beans.PropertyChangeEvent ; 30 import java.beans.PropertyChangeListener ; 31 import java.beans.PropertyChangeSupport ; 32 import java.io.IOException ; 33 import java.lang.reflect.InvocationTargetException ; 34 import java.net.URL ; 35 import java.net.MalformedURLException ; 36 import java.util.ArrayList ; 37 import java.util.Collection ; 38 import java.util.HashMap ; 39 import java.util.HashSet ; 40 import java.util.Iterator ; 41 import java.util.List ; 42 import java.util.Map ; 43 import java.util.Set ; 44 import javax.swing.SwingUtilities ; 45 import javax.swing.event.ChangeEvent ; 46 import javax.swing.event.ChangeListener ; 47 import javax.swing.text.BadLocationException ; 48 import javax.swing.text.Caret ; 49 import javax.swing.text.StyledDocument ; 50 import javax.swing.JEditorPane ; 51 52 import com.sun.source.tree.CompilationUnitTree; 53 import com.sun.source.tree.Tree; 54 import com.sun.source.tree.ImportTree; 55 import com.sun.source.util.SourcePositions; 56 import javax.lang.model.util.Elements; 57 import javax.lang.model.element.Element; 58 import javax.lang.model.element.ElementKind; 59 import javax.lang.model.element.TypeElement; 60 import javax.lang.model.element.VariableElement; 61 import org.netbeans.api.java.source.CancellableTask; 62 import org.netbeans.api.java.source.CompilationController; 63 import org.netbeans.api.java.source.ElementUtilities; 64 import org.netbeans.editor.Coloring; 65 import org.netbeans.modules.editor.highlights.spi.Highlight; 66 67 import org.openide.ErrorManager; 68 69 import org.openide.cookies.EditorCookie; 70 import org.openide.cookies.LineCookie; 71 import org.openide.filesystems.FileObject; 72 import org.openide.filesystems.FileStateInvalidException; 73 import org.openide.filesystems.URLMapper; 74 import org.openide.loaders.DataObject; 75 import org.openide.loaders.DataShadow; 76 import org.openide.loaders.DataObjectNotFoundException; 77 import org.openide.nodes.Node; 78 import org.openide.text.Line; 79 import org.openide.text.NbDocument; 80 import org.openide.util.Lookup; 81 import org.openide.util.LookupEvent; 82 import org.openide.util.LookupListener; 83 import org.openide.util.Utilities; 84 import org.openide.windows.TopComponent; 85 import org.netbeans.api.java.source.JavaSource; 86 import org.netbeans.api.java.source.JavaSource.Phase; 87 import org.netbeans.api.java.source.SourceUtils; 88 89 import org.netbeans.spi.debugger.jpda.EditorContext; 90 91 95 public class EditorContextImpl extends EditorContext { 96 97 private static String fronting = 98 System.getProperty ("netbeans.debugger.fronting"); 99 100 private PropertyChangeSupport pcs; 101 private Map annotationToURL = new HashMap (); 102 private ChangeListener changedFilesListener; 103 private Map timeStampToRegistry = new HashMap (); 104 private Set modifiedDataObjects; 105 private PropertyChangeListener editorObservableListener; 106 107 private Lookup.Result resDataObject; 108 private Lookup.Result resEditorCookie; 109 private Lookup.Result resNode; 110 111 private Object currentLock = new Object (); 112 private String currentURL = null; 113 private EditorCookie currentEditorCookie = null; 115 116 117 { 118 pcs = new PropertyChangeSupport (this); 119 120 resDataObject = Utilities.actionsGlobalContext().lookup(new Lookup.Template(DataObject.class)); 121 resDataObject.addLookupListener(new EditorLookupListener(DataObject.class)); 122 123 resEditorCookie = Utilities.actionsGlobalContext().lookup(new Lookup.Template(EditorCookie.class)); 124 resEditorCookie.addLookupListener(new EditorLookupListener(EditorCookie.class)); 125 126 resNode = Utilities.actionsGlobalContext().lookup(new Lookup.Template(Node.class)); 127 resNode.addLookupListener(new EditorLookupListener(Node.class)); 128 129 } 130 131 132 139 public boolean showSource (String url, int lineNumber, Object timeStamp) { 140 Line l = getLine (url, lineNumber, timeStamp); if (l == null) { 142 ErrorManager.getDefault().log(ErrorManager.WARNING, 143 "Show Source: Have no line for URL = "+url+", line number = "+lineNumber); 144 return false; 145 } 146 if (fronting != null) { 147 if (fronting.equals ("true")) 148 l.show (Line.SHOW_TOFRONT); else 150 l.show (Line.SHOW_GOTO); 151 return true; 152 } 153 if (Utilities.isWindows()) 154 l.show (Line.SHOW_TOFRONT); else 156 l.show (Line.SHOW_GOTO); 157 return true; 158 } 159 160 167 public boolean showSource (String url, int lineNumber, int column, int length, Object timeStamp) { 168 Line l = getLine (url, lineNumber, timeStamp); if (l == null) { 170 ErrorManager.getDefault().log(ErrorManager.WARNING, 171 "Show Source: Have no line for URL = "+url+", line number = "+lineNumber); 172 return false; 173 } 174 if (fronting != null) { 175 if (fronting.equals ("true")) 176 l.show (Line.SHOW_TOFRONT, column); else 178 l.show (Line.SHOW_GOTO, column); 179 return true; 180 } 181 if (Utilities.isWindows()) 182 l.show (Line.SHOW_TOFRONT, column); else 184 l.show (Line.SHOW_GOTO, column); 185 return true; 186 } 187 188 189 194 public void createTimeStamp (Object timeStamp) { 195 modifiedDataObjects = new HashSet ( 196 DataObject.getRegistry ().getModifiedSet () 197 ); 198 Registry r = new Registry (); 199 timeStampToRegistry.put (timeStamp, r); 200 Iterator i = modifiedDataObjects.iterator (); 201 while (i.hasNext ()) 202 r.register ((DataObject) i.next ()); 203 if (changedFilesListener == null) { 204 changedFilesListener = new ChangedFilesListener (); 205 DataObject.getRegistry ().addChangeListener (changedFilesListener); 206 } 207 } 208 209 214 public void disposeTimeStamp (Object timeStamp) { 215 timeStampToRegistry.remove (timeStamp); 216 if (timeStampToRegistry.isEmpty ()) { 217 DataObject.getRegistry ().removeChangeListener (changedFilesListener); 218 changedFilesListener = null; 219 } 220 } 221 222 public Object annotate ( 223 String url, 224 int lineNumber, 225 String annotationType, 226 Object timeStamp 227 ) { 228 Line l = getLine ( 229 url, 230 lineNumber, 231 timeStamp 232 ); 233 if (l == null) return null; 234 DebuggerAnnotation annotation = 235 new DebuggerAnnotation (annotationType, l); 236 annotationToURL.put (annotation, url); 237 238 return annotation; 239 } 240 241 public Object annotate ( 242 String url, 243 int startPosition, 244 int endPosition, 245 String annotationType, 246 Object timeStamp 247 ) { 248 Coloring coloring; 249 if (EditorContext.CURRENT_LAST_OPERATION_ANNOTATION_TYPE.equals(annotationType)) { 250 coloring = new Coloring(null, Coloring.FONT_MODE_DEFAULT, null, null, getColor(annotationType), null, null); 251 } else { 252 coloring = new Coloring(null, null, getColor(annotationType)); 253 } 254 Highlight highlight = new OperationHighlight(coloring, startPosition, endPosition); 255 DebuggerAnnotation annotation; 256 try { 257 annotation = new DebuggerAnnotation(annotationType, highlight, URLMapper.findFileObject(new URL (url))); 258 } catch (MalformedURLException ex) { 259 RuntimeException rex = new RuntimeException ("Bad URL: "+url); 260 rex.initCause(ex); 261 throw rex; 262 } 263 annotationToURL.put (annotation, url); 264 265 return annotation; 266 } 267 268 private static Color getColor(String annotationType) { 269 if (EditorContext.BREAKPOINT_ANNOTATION_TYPE.equals(annotationType)) { 270 return new Color (0xFC9D9F); 271 } else if (EditorContext.CURRENT_LINE_ANNOTATION_TYPE.equals(annotationType) || 272 EditorContext.CURRENT_OUT_OPERATION_ANNOTATION_TYPE.equals(annotationType)) { 273 return new Color (0xBDE6AA); 274 } else if (EditorContext.CURRENT_EXPRESSION_CURRENT_LINE_ANNOTATION_TYPE.equals(annotationType)) { 275 return new Color (0xE9FFE6); } else if (EditorContext.CURRENT_LAST_OPERATION_ANNOTATION_TYPE.equals(annotationType)) { 277 return new Color (0x99BB8A); 278 } else { 279 return new Color (0x0000FF); 280 } 281 } 282 283 288 public void removeAnnotation ( 289 Object a 290 ) { 291 if (a instanceof Collection ) { 292 Collection annotations = ((Collection ) a); 293 for (Iterator it = annotations.iterator(); it.hasNext(); ) { 294 removeAnnotation((DebuggerAnnotation) it.next()); 295 } 296 } else { 297 removeAnnotation((DebuggerAnnotation) a); 298 } 299 } 300 301 private void removeAnnotation(DebuggerAnnotation annotation) { 302 annotation.detach (); 303 304 if (annotationToURL.remove (annotation) == null) { 305 return; } 307 } 308 309 317 public int getLineNumber ( 318 Object annotation, 319 Object timeStamp 320 ) { 321 DebuggerAnnotation a = (DebuggerAnnotation) annotation; 322 if (timeStamp == null) 323 return a.getLine ().getLineNumber () + 1; 324 String url = (String ) annotationToURL.get (a); 325 Line.Set lineSet = getLineSet (url, timeStamp); 326 return lineSet.getOriginalLineNumber (a.getLine ()) + 1; 327 } 328 329 335 public void updateTimeStamp (Object timeStamp, String url) { 336 Registry registry = (Registry) timeStampToRegistry.get (timeStamp); 337 registry.register (getDataObject (url)); 338 } 339 340 345 public int getCurrentLineNumber () { 346 if (SwingUtilities.isEventDispatchThread()) { 347 return getCurrentLineNumber_(); 348 } else { 349 final int[] ln = new int[1]; 350 try { 351 SwingUtilities.invokeAndWait(new Runnable () { 352 public void run() { 353 ln[0] = getCurrentLineNumber_(); 354 } 355 }); 356 } catch (InvocationTargetException ex) { 357 ErrorManager.getDefault().notify(ex.getTargetException()); 358 } catch (InterruptedException ex) { 359 ErrorManager.getDefault().notify(ex); 360 } 361 return ln[0]; 362 } 363 } 364 365 private int getCurrentLineNumber_() { 366 EditorCookie e = getCurrentEditorCookie (); 367 if (e == null) return -1; 368 JEditorPane ep = getCurrentEditor (); 369 if (ep == null) return -1; 370 StyledDocument d = e.getDocument (); 371 if (d == null) return -1; 372 Caret caret = ep.getCaret (); 373 if (caret == null) return -1; 374 int ln = NbDocument.findLineNumber ( 375 d, 376 caret.getDot () 377 ); 378 return ln + 1; 379 } 380 381 386 public String getCurrentClassName () { 387 String currentClass = getCurrentElement(ElementKind.CLASS); 388 if (currentClass == null) return ""; 389 else return currentClass; 390 } 391 392 397 public String getCurrentURL () { 398 synchronized (currentLock) { 399 if (currentURL == null) { 400 DataObject[] nodes = (DataObject[])resDataObject.allInstances().toArray(new DataObject[0]); 401 402 currentURL = ""; 403 if (nodes.length != 1) 404 return currentURL; 405 406 DataObject dO = nodes[0]; 407 if (dO instanceof DataShadow) 408 dO = ((DataShadow) dO).getOriginal (); 409 410 try { 411 currentURL = dO.getPrimaryFile ().getURL ().toString (); 412 } catch (FileStateInvalidException ex) { 413 } 415 } 416 417 return currentURL; 418 } 419 } 420 421 426 public String getCurrentMethodName () { 427 String currentMethod = getCurrentElement(ElementKind.METHOD); 428 if (currentMethod == null) return ""; 429 else return currentMethod; 430 } 431 432 437 public String getCurrentFieldName () { 438 String currentField = getCurrentElement(ElementKind.FIELD); 439 if (currentField == null) return ""; 440 else return currentField; 441 } 443 444 449 public String getSelectedIdentifier () { 450 if (SwingUtilities.isEventDispatchThread()) { 451 return getSelectedIdentifier_(); 452 } else { 453 final String [] si = new String [1]; 454 try { 455 SwingUtilities.invokeAndWait(new Runnable () { 456 public void run() { 457 si[0] = getSelectedIdentifier_(); 458 } 459 }); 460 } catch (InvocationTargetException ex) { 461 ErrorManager.getDefault().notify(ex.getTargetException()); 462 } catch (InterruptedException ex) { 463 ErrorManager.getDefault().notify(ex); 464 } 465 return si[0]; 466 } 467 } 468 469 private String getSelectedIdentifier_() { 470 JEditorPane ep = getCurrentEditor (); 471 if (ep == null) return null; 472 String s = ep.getSelectedText (); 473 if (s == null) return null; 474 if (Utilities.isJavaIdentifier (s)) return s; 475 return null; 476 } 477 478 483 public String getSelectedMethodName () { 484 if (SwingUtilities.isEventDispatchThread()) { 485 return getSelectedMethodName_(); 486 } else { 487 final String [] mn = new String [1]; 488 try { 489 SwingUtilities.invokeAndWait(new Runnable () { 490 public void run() { 491 mn[0] = getSelectedMethodName_(); 492 } 493 }); 494 } catch (InvocationTargetException ex) { 495 ErrorManager.getDefault().notify(ex.getTargetException()); 496 } catch (InterruptedException ex) { 497 ErrorManager.getDefault().notify(ex); 498 } 499 return mn[0]; 500 } 501 } 502 503 private String getSelectedMethodName_() { 504 EditorCookie e = getCurrentEditorCookie (); 505 if (e == null) return ""; 506 JEditorPane ep = getCurrentEditor (); 507 if (ep == null) return ""; 508 StyledDocument doc = e.getDocument (); 509 if (doc == null) return ""; 510 int offset = ep.getCaret ().getDot (); 511 String t = null; 512 517 int line = NbDocument.findLineNumber ( 518 doc, 519 offset 520 ); 521 int col = NbDocument.findLineColumn ( 522 doc, 523 offset 524 ); 525 try { 526 javax.swing.text.Element lineElem = 527 org.openide.text.NbDocument.findLineRootElement (doc). 528 getElement (line); 529 530 if (lineElem == null) return ""; 531 int lineStartOffset = lineElem.getStartOffset (); 532 int lineLen = lineElem.getEndOffset () - lineStartOffset; 533 t = doc.getText (lineStartOffset, lineLen); 535 536 int identStart = col; 537 while ( identStart > 0 && 538 Character.isJavaIdentifierPart ( 539 t.charAt (identStart - 1) 540 ) 541 ) identStart--; 542 543 int identEnd = col; 544 while (identEnd < lineLen && 545 Character.isJavaIdentifierPart (t.charAt (identEnd)) 546 ) { 547 identEnd++; 548 } 549 int i = t.indexOf ('(', identEnd); 550 if (i < 0) return ""; 551 if (t.substring (identEnd, i).trim ().length () > 0) return ""; 552 553 if (identStart == identEnd) return ""; 554 return t.substring (identStart, identEnd); 555 } catch (javax.swing.text.BadLocationException ex) { 556 return ""; 557 } 558 } 559 560 576 577 587 public int getFieldLineNumber ( 588 String url, 589 final String className, 590 final String fieldName 591 ) { 592 final DataObject dataObject = getDataObject (url); 593 if (dataObject == null) return -1; 594 JavaSource js = JavaSource.forFileObject(dataObject.getPrimaryFile()); 595 if (js == null) return -1; 596 final int[] result = new int[] {-1}; 597 598 try { 599 js.runUserActionTask(new CancellableTask<CompilationController>() { 600 public void cancel() { 601 } 602 public void run(CompilationController ci) throws Exception { 603 Elements elms = ci.getElements(); 604 TypeElement classElement = elms.getTypeElement(className); 605 if (classElement == null) return ; 606 List classMemberElements = elms.getAllMembers(classElement); 607 for (Iterator it = classMemberElements.iterator(); it.hasNext(); ) { 608 Element elm = (Element) it.next(); 609 if (elm.getKind() == ElementKind.FIELD) { 610 String name = ((VariableElement) elm).getSimpleName().toString(); 611 if (name.equals(fieldName)) { 612 SourcePositions positions = ci.getTrees().getSourcePositions(); 613 Tree tree = SourceUtils.treeFor(ci, elm); 614 int pos = (int)positions.getStartPosition(ci.getCompilationUnit(), tree); 615 EditorCookie editor = (EditorCookie) dataObject.getCookie(EditorCookie.class); 616 result[0] = NbDocument.findLineNumber(editor.getDocument(), pos); 617 } 619 } 620 } 621 } 622 },true); 623 } catch (IOException ioex) { 624 return -1; 626 } 627 return result[0]; 628 634 654 } 655 656 664 public String getClassName ( 665 String url, 666 int lineNumber 667 ) { 668 DataObject dataObject = getDataObject (url); 669 if (dataObject == null) return null; 670 JavaSource js = JavaSource.forFileObject(dataObject.getPrimaryFile()); 671 if (js == null) return ""; 672 EditorCookie ec = (EditorCookie) dataObject.getCookie(EditorCookie.class); 673 if (ec == null) return ""; 674 StyledDocument doc; 675 try { 676 doc = ec.openDocument(); 677 } catch (IOException ex) { 678 return ""; 679 } 680 try { 681 final int offset = NbDocument.findLineOffset(doc, lineNumber - 1); 682 final String [] result = new String [] {""}; 683 js.runUserActionTask(new CancellableTask<CompilationController>() { 684 public void cancel() { 685 } 686 public void run(CompilationController ci) throws Exception { 687 if (ci.toPhase(Phase.RESOLVED).compareTo(Phase.RESOLVED) < 0) return; 689 690 Scope scope = ci.getTreeUtilities().scopeFor(offset); 691 TypeElement te = scope.getEnclosingClass(); 692 result[0] = ElementUtilities.getBinaryName(te); 693 } 694 }, true); 695 return result[0]; 696 } catch (IOException ioex) { 697 return ""; 699 } catch (IndexOutOfBoundsException ioobex) { 700 return null; 702 } 703 732 } 733 734 735 public Operation[] getOperations(String url, final int lineNumber, 736 final BytecodeProvider bytecodeProvider) { 737 DataObject dataObject = getDataObject (url); 738 if (dataObject == null) return null; 739 JavaSource js = JavaSource.forFileObject(dataObject.getPrimaryFile()); 740 if (js == null) return null; 741 EditorCookie ec = (EditorCookie) dataObject.getCookie(EditorCookie.class); 742 if (ec == null) return null; 743 final StyledDocument doc; 744 try { 745 doc = ec.openDocument(); 746 } catch (IOException ex) { 747 return null; 748 } 749 final int offset = findLineOffset(doc, (int) lineNumber); 750 final Operation ops[][] = new Operation[1][]; 751 try { 752 js.runUserActionTask(new CancellableTask<CompilationController>() { 753 public void cancel() { 754 } 755 public void run(CompilationController ci) throws Exception { 756 if (ci.toPhase(Phase.RESOLVED).compareTo(Phase.RESOLVED) < 0) return; 758 759 Scope scope = ci.getTreeUtilities().scopeFor(offset); 760 Element method = scope.getEnclosingMethod(); 761 if (method == null) { 762 ops[0] = new Operation[] {}; 763 return ; 764 } 765 Tree methodTree = SourceUtils.treeFor(ci, method); 766 CompilationUnitTree cu = ci.getCompilationUnit(); 767 ExpressionScanner scanner = new ExpressionScanner(lineNumber, cu, ci.getTrees().getSourcePositions()); 768 ExpressionScanner.ExpressionsInfo info = new ExpressionScanner.ExpressionsInfo(); 769 List <Tree> expTrees = methodTree.accept(scanner, info); 770 771 if (expTrees == null || expTrees.size() == 0) { 773 ops[0] = new Operation[] {}; 774 return ; 775 } 776 SourcePositions sp = ci.getTrees().getSourcePositions(); 778 int treeStartLine = 779 (int) cu.getLineMap().getLineNumber( 780 sp.getStartPosition(cu, expTrees.get(0))); 781 int treeEndLine = 782 (int) cu.getLineMap().getLineNumber( 783 sp.getEndPosition(cu, expTrees.get(expTrees.size() - 1))); 784 785 int[] indexes = bytecodeProvider.indexAtLines(treeStartLine, treeEndLine); 786 if (indexes == null) { 787 return ; 788 } 789 Map <Tree, Operation> nodeOperations = new HashMap <Tree, Operation>(); 790 ops[0] = AST2Bytecode.matchSourceTree2Bytecode( 791 cu, 792 ci, 793 expTrees, info, bytecodeProvider.byteCodes(), 794 indexes, 795 bytecodeProvider.constantPool(), 796 new OperationCreationDelegateImpl(), 797 nodeOperations); 798 if (ops[0] != null) { 799 assignNextOperations(methodTree, cu, ci, bytecodeProvider, expTrees, info, nodeOperations); 800 } 801 } 802 },true); 803 } catch (IOException ioex) { 804 ErrorManager.getDefault().notify(ioex); 805 return null; 806 } 807 return ops[0]; 808 } 809 810 private void assignNextOperations(Tree methodTree, 811 CompilationUnitTree cu, 812 CompilationController ci, 813 BytecodeProvider bytecodeProvider, 814 List <Tree> treeNodes, 815 ExpressionScanner.ExpressionsInfo info, 816 Map <Tree, Operation> nodeOperations) { 817 int length = treeNodes.size(); 818 for (int treeIndex = 0; treeIndex < length; treeIndex++) { 819 Tree node = treeNodes.get(treeIndex); 820 Set <Tree> nextNodes = info.getNextExpressions(node); 821 if (nextNodes != null) { 822 EditorContext.Operation op = nodeOperations.get(node); 823 if (op == null) { 824 for (int backIndex = treeIndex - 1; backIndex >= 0; backIndex--) { 825 node = treeNodes.get(backIndex); 826 op = nodeOperations.get(node); 827 if (op != null) break; 828 } 829 } 830 if (op != null) { 831 for (Tree t : nextNodes) { 832 EditorContext.Operation nextOp = nodeOperations.get(t); 833 if (nextOp == null) { 834 SourcePositions sp = ci.getTrees().getSourcePositions(); 835 int treeStartLine = 836 (int) cu.getLineMap().getLineNumber( 837 sp.getStartPosition(cu, t)); 838 ExpressionScanner scanner = new ExpressionScanner(treeStartLine, cu, ci.getTrees().getSourcePositions()); 839 ExpressionScanner.ExpressionsInfo newInfo = new ExpressionScanner.ExpressionsInfo(); 840 List <Tree> newExpTrees = methodTree.accept(scanner, newInfo); 841 treeStartLine = 842 (int) cu.getLineMap().getLineNumber( 843 sp.getStartPosition(cu, newExpTrees.get(0))); 844 int treeEndLine = 845 (int) cu.getLineMap().getLineNumber( 846 sp.getEndPosition(cu, newExpTrees.get(newExpTrees.size() - 1))); 847 848 int[] indexes = bytecodeProvider.indexAtLines(treeStartLine, treeEndLine); 849 Map <Tree, Operation> newNodeOperations = new HashMap <Tree, Operation>(); 850 Operation[] newOps = AST2Bytecode.matchSourceTree2Bytecode( 851 cu, 852 ci, 853 newExpTrees, newInfo, bytecodeProvider.byteCodes(), 854 indexes, 855 bytecodeProvider.constantPool(), 856 new OperationCreationDelegateImpl(), 857 newNodeOperations); 858 nextOp = newNodeOperations.get(t); 859 if (nextOp == null) { 860 System.err.println("Next operation not found!"); 862 continue; 863 } 864 } 865 addNextOperationTo(op, nextOp); 866 } 867 } 868 } 869 } 870 871 } 872 873 876 private static int findLineOffset(StyledDocument doc, int lineNumber) { 877 int offset; 878 try { 879 offset = NbDocument.findLineOffset (doc, lineNumber - 1); 880 int offset2 = NbDocument.findLineOffset (doc, lineNumber); 881 try { 882 String lineStr = doc.getText(offset, offset2 - offset); 883 for (int i = 0; i < lineStr.length(); i++) { 884 if (!Character.isWhitespace(lineStr.charAt(i))) { 885 offset += i; 886 break; 887 } 888 } 889 } catch (BadLocationException ex) { 890 } 892 } catch (IndexOutOfBoundsException ioobex) { 893 return -1; 894 } 895 return offset; 896 } 897 898 905 public String [] getImports ( 906 String url 907 ) { 908 DataObject dataObject = getDataObject (url); 909 if (dataObject == null) return new String [0]; 910 JavaSource js = JavaSource.forFileObject(dataObject.getPrimaryFile()); 911 if (js == null) return new String [0]; 912 final List <String > imports = new ArrayList <String >(); 913 try { 914 js.runUserActionTask(new CancellableTask<CompilationController>() { 915 public void cancel() { 916 } 917 public void run(CompilationController ci) throws Exception { 918 if (ci.toPhase(Phase.PARSED).compareTo(Phase.PARSED) < 0) 919 return; 920 921 List importDecl = ci.getCompilationUnit().getImports(); 922 int i = 0; 923 for (Iterator it = importDecl.iterator(); it.hasNext(); i++) { 924 ImportTree itree = (ImportTree) it.next(); 925 String importStr = itree.getQualifiedIdentifier().toString(); 926 imports.add(importStr); 927 } 928 } 929 }, true); 930 } catch (IOException ioex) { 931 return new String [0]; 932 } 933 return imports.toArray(new String [0]); 934 945 } 946 947 952 public void addPropertyChangeListener (PropertyChangeListener l) { 953 pcs.addPropertyChangeListener (l); 954 } 955 956 961 public void removePropertyChangeListener (PropertyChangeListener l) { 962 pcs.removePropertyChangeListener (l); 963 } 964 965 971 public void addPropertyChangeListener ( 972 String propertyName, 973 PropertyChangeListener l 974 ) { 975 pcs.addPropertyChangeListener (propertyName, l); 976 } 977 978 984 public void removePropertyChangeListener ( 985 String propertyName, 986 PropertyChangeListener l 987 ) { 988 pcs.removePropertyChangeListener (propertyName, l); 989 } 990 991 992 994 1004 1005 private String getCurrentElement(final ElementKind kind) { 1006 Node[] nodes = TopComponent.getRegistry ().getCurrentNodes (); 1007 if (nodes == null) return null; 1008 if (nodes.length != 1) return null; 1009 DataObject dataObject = nodes[0].getCookie(DataObject.class); 1010 if (dataObject == null) return null; 1011 JavaSource js = JavaSource.forFileObject(dataObject.getPrimaryFile()); 1012 if (js == null) return null; 1013 final int offset = org.netbeans.editor.Registry.getMostActiveComponent().getCaretPosition(); 1015 final String [] currentElementPtr = new String [] { null }; 1016 try { 1017 js.runUserActionTask(new CancellableTask<CompilationController>() { 1018 public void cancel() { 1019 } 1020 public void run(CompilationController ci) throws Exception { 1021 if (ci.toPhase(Phase.RESOLVED).compareTo(Phase.RESOLVED) < 0) return; 1023 1024 if (kind == ElementKind.CLASS) { 1025 Scope scope = ci.getTreeUtilities().scopeFor(offset); 1026 TypeElement te = scope.getEnclosingClass(); 1027 if (te != null) { 1028 currentElementPtr[0] = ElementUtilities.getBinaryName(te); 1029 } 1030 } else if (kind == ElementKind.METHOD) { 1031 Scope scope = ci.getTreeUtilities().scopeFor(offset); 1032 Element el = scope.getEnclosingMethod(); 1033 if (el != null) { 1034 currentElementPtr[0] = el.getSimpleName().toString(); 1035 } 1036 } else if (kind == ElementKind.FIELD) { 1037 Element el = ci.getTrees().getElement(ci.getTreeUtilities().pathFor(offset)); 1038 if (el != null && el.getKind() == ElementKind.FIELD) { 1039 currentElementPtr[0] = el.getSimpleName().toString(); 1040 } 1041 } 1042 } 1043 }, true); 1044 } catch (IOException ioex) { 1045 ErrorManager.getDefault().notify(ioex); 1046 return null; 1047 } 1048 return currentElementPtr[0]; 1049 } 1050 1051 private JEditorPane getCurrentEditor () { 1052 EditorCookie e = getCurrentEditorCookie (); 1053 if (e == null) return null; 1054 JEditorPane [] op = e.getOpenedPanes (); 1055 if ((op == null) || (op.length < 1)) return null; 1057 return op [0]; 1058 } 1059 1060 private EditorCookie getCurrentEditorCookie () { 1061 synchronized (currentLock) { 1062 if (currentEditorCookie == null) { 1063 TopComponent tc = TopComponent.getRegistry().getActivated(); 1064 if (tc != null) { 1065 currentEditorCookie = (EditorCookie) tc.getLookup().lookup(EditorCookie.class); 1066 } 1067 if (currentEditorCookie instanceof EditorCookie.Observable) { 1069 if (editorObservableListener == null) { 1070 editorObservableListener = new EditorLookupListener(EditorCookie.Observable.class); 1071 } 1072 ((EditorCookie.Observable) currentEditorCookie).addPropertyChangeListener(editorObservableListener); 1073 } 1074 } 1075 return currentEditorCookie; 1076 } 1077 } 1078 1079 private Line.Set getLineSet (String url, Object timeStamp) { 1080 DataObject dataObject = getDataObject (url); 1081 if (dataObject == null) return null; 1082 1083 if (timeStamp != null) { 1084 Registry registry = (Registry) timeStampToRegistry.get (timeStamp); 1086 if (registry != null) { 1087 Line.Set ls = registry.getLineSet (dataObject); 1088 if (ls != null) return ls; 1089 } 1090 } 1091 1092 LineCookie lineCookie = (LineCookie) dataObject.getCookie 1094 (LineCookie.class); 1095 if (lineCookie == null) return null; 1096 return lineCookie.getLineSet (); 1097 } 1098 1099 private Line getLine (String url, int lineNumber, Object timeStamp) { 1100 Line.Set ls = getLineSet (url, timeStamp); 1101 if (ls == null) return null; 1102 try { 1103 if (timeStamp == null) 1104 return ls.getCurrent (lineNumber - 1); 1105 else 1106 return ls.getOriginal (lineNumber - 1); 1107 } catch (IndexOutOfBoundsException e) { 1108 } catch (IllegalArgumentException e) { 1109 } 1110 return null; 1111 } 1112 1113 private static DataObject getDataObject (String url) { 1114 FileObject file; 1115 try { 1116 file = URLMapper.findFileObject (new URL (url)); 1117 } catch (MalformedURLException e) { 1118 return null; 1119 } 1120 1121 if (file == null) return null; 1122 try { 1123 return DataObject.find (file); 1124 } catch (DataObjectNotFoundException ex) { 1125 return null; 1126 } 1127 } 1128 1129 private static class Registry { 1130 1131 private Map dataObjectToLineSet = new HashMap (); 1132 1133 void register (DataObject dataObject) { 1134 LineCookie lc = (LineCookie) dataObject.getCookie (LineCookie.class); 1135 if (lc == null) return; 1136 dataObjectToLineSet.put (dataObject, lc.getLineSet ()); 1137 } 1138 1139 Line.Set getLineSet (DataObject dataObject) { 1140 return (Line.Set) dataObjectToLineSet.get (dataObject); 1141 } 1142 } 1143 1144 private class ChangedFilesListener implements ChangeListener { 1145 public void stateChanged (ChangeEvent e) { 1146 Set newDOs = new HashSet ( 1147 DataObject.getRegistry ().getModifiedSet () 1148 ); 1149 newDOs.removeAll (modifiedDataObjects); 1150 Iterator i1 = timeStampToRegistry.values ().iterator (); 1151 while (i1.hasNext ()) { 1152 Registry r = (Registry) i1.next (); 1153 Iterator i2 = newDOs.iterator (); 1154 while (i2.hasNext ()) 1155 r.register ((DataObject) i2.next ()); 1156 } 1157 modifiedDataObjects = new HashSet ( 1158 DataObject.getRegistry ().getModifiedSet () 1159 ); 1160 } 1161 } 1162 1163 private class EditorLookupListener extends Object implements LookupListener, PropertyChangeListener { 1164 1165 private Class type; 1166 1167 public EditorLookupListener(Class type) { 1168 this.type = type; 1169 } 1170 1171 public void resultChanged(LookupEvent ev) { 1172 if (type == DataObject.class) { 1173 synchronized (currentLock) { 1174 currentURL = null; 1175 if (currentEditorCookie instanceof EditorCookie.Observable) { 1177 ((EditorCookie.Observable) currentEditorCookie). 1178 removePropertyChangeListener(editorObservableListener); 1179 } 1180 currentEditorCookie = null; 1181 } 1182 pcs.firePropertyChange (TopComponent.Registry.PROP_CURRENT_NODES, null, null); 1183 } else if (type == EditorCookie.class) { 1184 synchronized (currentLock) { 1185 currentURL = null; 1186 if (currentEditorCookie instanceof EditorCookie.Observable) { 1188 ((EditorCookie.Observable) currentEditorCookie). 1189 removePropertyChangeListener(editorObservableListener); 1190 } 1191 currentEditorCookie = null; 1192 } 1193 pcs.firePropertyChange (TopComponent.Registry.PROP_CURRENT_NODES, null, null); 1194 } else if (type == Node.class) { 1195 synchronized (currentLock) { 1196 } 1198 pcs.firePropertyChange (TopComponent.Registry.PROP_CURRENT_NODES, null, null); 1199 } 1200 } 1201 1202 public void propertyChange(PropertyChangeEvent evt) { 1203 if (evt.getPropertyName().equals(EditorCookie.Observable.PROP_OPENED_PANES)) { 1204 pcs.firePropertyChange (EditorCookie.Observable.PROP_OPENED_PANES, null, null); 1205 } 1206 } 1207 1208 } 1209 1210 private static final class OperationHighlight implements Highlight { 1211 1212 private Coloring coloring; 1213 private int start; 1214 private int end; 1215 1216 1217 public OperationHighlight(Coloring coloring, int start, int end) { 1218 this.coloring = coloring; 1219 this.start = start; 1220 this.end = end; 1221 } 1222 1223 public int getStart() { 1224 return start; 1225 } 1226 1227 public int getEnd() { 1228 return end; 1229 } 1230 1231 public Coloring getColoring() { 1232 return coloring; 1233 } 1234 1235 } 1236 1237 private class OperationCreationDelegateImpl implements AST2Bytecode.OperationCreationDelegate { 1238 1249 public Operation createMethodOperation( 1250 Position startPosition, 1251 Position endPosition, 1252 Position methodStartPosition, 1253 Position methodEndPosition, 1254 String methodName, 1255 String methodClassType, 1256 int bytecodeIndex) { 1257 return EditorContextImpl.this.createMethodOperation( 1258 startPosition, 1259 endPosition, 1260 methodStartPosition, 1261 methodEndPosition, 1262 methodName, 1263 methodClassType, 1264 bytecodeIndex); 1265 } 1266 public Position createPosition( 1267 int offset, 1268 int line, 1269 int column) { 1270 return EditorContextImpl.this.createPosition( 1271 offset, 1272 line, 1273 column); 1274 } 1275 public void addNextOperationTo(Operation operation, Operation next) { 1276 EditorContextImpl.this.addNextOperationTo(operation, next); 1277 } 1278 } 1279 1280} 1281 | Popular Tags |