1 19 20 package org.netbeans.modules.tasklist.javaparser; 21 22 import javax.swing.text.*; 23 import javax.swing.event.*; 24 import java.awt.*; 25 import java.awt.event.*; 26 import javax.swing.*; 27 import java.util.List ; 28 import java.util.ArrayList ; 29 import java.util.Arrays ; 30 import java.util.Collections ; 31 import java.util.Comparator ; 32 import java.util.Iterator ; 33 import org.openide.ErrorManager; 34 import org.openide.cookies.SourceCookie; 35 import org.openide.explorer.view.*; 36 import org.openide.nodes.*; 37 import org.netbeans.modules.java.*; 38 import org.openide.filesystems.*; 39 40 import org.openide.src.*; 41 42 import org.openide.loaders.DataObject; 43 import org.openide.src.Identifier; 44 import org.openide.src.Import; 45 import org.openide.src.SourceElement; 46 import org.openide.src.SourceException; 47 import org.openide.util.NbBundle; 48 import org.openide.util.Utilities; 49 50 import org.openide.cookies.LineCookie; 51 import org.openide.loaders.DataObject; 52 import org.openide.text.Line; 53 import org.openide.ErrorManager; 54 55 import java.util.TreeSet ; 56 import java.lang.reflect.Modifier ; 57 import java.io.IOException ; 58 59 import org.netbeans.editor.ext.java.*; 60 import org.netbeans.modules.editor.java.*; 61 import org.netbeans.modules.java.Parsing; 62 import org.netbeans.modules.java.ParserMessage; 63 import org.netbeans.modules.java.parser.*; 64 65 import org.netbeans.modules.tasklist.core.ConfPanel; 66 import org.netbeans.modules.tasklist.core.TLUtils; 67 import org.netbeans.modules.tasklist.client.*; 68 import org.netbeans.modules.tasklist.providers.DocumentSuggestionProvider; 69 import org.netbeans.modules.tasklist.providers.SuggestionContext; 70 71 72 87 88 89 public class ErrorSuggester extends DocumentSuggestionProvider 90 implements Parsing.Listener { 91 92 final private static String TYPE = "nb-java-errors"; 98 public String getType() { 99 return TYPE; 100 } 101 102 private SuggestionContext env; 103 private Object request = null; 104 105 123 124 126 private static void requestParse(JavaDataObject jdo, boolean now) { 127 JavaParser parser = (JavaParser)jdo.getCookie(JavaParser.class); 132 if (parser == null) { 133 System.out.println("Parser not found!"); 134 return; 135 } 136 final ParseSourceRequest req; 137 req = new ParseSourceRequest((Object )JavaParser.DEEP_PARSER); 138 boolean ignoreClean = true; 139 int priority = now ? 140 JavaParser.PRIORITY_DEMAND : 141 JavaParser.PRIORITY_NORMAL; 142 org.openide.util.Task t = parser.parse(priority, ignoreClean, false, req); 143 } 144 145 public void notifyStop() { 146 Parsing.removeParsingListener(this); 147 } 148 149 private void errorsChanged(SuggestionContext env) { 152 List newTasks = scan(env); 153 SuggestionManager manager = SuggestionManager.getDefault(); 154 if ((newTasks == null) && (showingTasks == null)) { 155 return; 156 } 157 158 manager.register(TYPE, newTasks, showingTasks); 159 showingTasks = newTasks; 160 } 161 162 171 public List scan(SuggestionContext env) { 172 ArrayList tasks = null; 173 SuggestionManager manager = SuggestionManager.getDefault(); 174 175 184 DataObject dataObject = null; 185 try { 186 dataObject = DataObject.find(env.getFileObject()); 187 } catch (IOException ex) { 188 return null; 189 } 190 if (manager.isEnabled(TYPE)) { 191 ParserMessage[] errors = getMessages(env); 194 if ((errors != null) && (errors.length > 0)) { 195 Arrays.sort(errors, new Comparator () { 196 public int compare(Object o1, Object o2) { 197 ParserMessage a = (ParserMessage)o1; 198 ParserMessage b = (ParserMessage)o2; 199 return a.getLineNumber() - b.getLineNumber(); 200 } 201 }); 202 int n = errors.length; 203 if (n > 30) { 204 n = 30; 205 } 206 for (int i = 0; i < n; i++) { 207 ParserMessage err = errors[i]; 208 String summary = err.getDescription(); 209 210 SuggestionAgent s = manager.createSuggestion(TYPE, 211 summary, 212 null, 213 this); 214 215 Line line = TLUtils.getLineByNumber(dataObject, err.getLineNumber()); 222 s.setLine(line); 223 if (summary.indexOf("warning: ") != -1) { 224 s.setIcon(Utilities.loadImage("org/netbeans/modules/tasklist/javaparser/warning.gif")); } 227 s.setPriority(SuggestionPriority.HIGH); 228 if (tasks == null) { 229 tasks = new ArrayList (errors.length); 230 } 231 tasks.add(s.getSuggestion()); 232 233 235 handleError(manager, tasks, env.getDocument(), dataObject, 236 summary, line, err.getLineNumber(), 237 err.getColumn()); 238 } 240 } 241 } 242 return tasks; 243 } 244 245 263 public void handleError(SuggestionManager manager, List tasks, 264 final Document doc, final DataObject dobj, 265 String summary, 266 Line line, 267 int lineNumber, 268 int column) { 269 if ( 270 summary.startsWith("cannot resolve symbol")) { 279 285 int lix2 = summary.indexOf("location: package"); if (lix2 != -1) { 287 return; 292 } 293 294 295 int ix = summary.indexOf("symbol : class "); 296 if (ix != -1) { 297 ix += "symbol : class ".length(); 299 int eix = summary.indexOf(' ', ix); 300 if (eix != -1) { 301 String symbol = summary.substring(ix,eix); 302 303 306 JCFinder finder = getSensitiveFinder(); 312 List list = finder.findClasses(null, symbol, true); 313 if ((list != null) && (list.size() > 0)) { 314 Iterator itr = list.iterator(); 317 while (itr.hasNext()) { 318 final JCClass classname = (JCClass)itr.next(); 319 SuggestionPerformer action = 320 new ImportPerformer(lineNumber, 321 dobj, doc, 322 classname); 323 String fname = dobj.getPrimaryFile().getNameExt(); 324 String sum = NbBundle.getMessage(ErrorSuggester.class, 325 "ImportClassSg", classname, fname); SuggestionAgent s = 327 manager.createSuggestion(TYPE, 328 sum, 329 action, 330 this); 331 332 s.setLine(line); 333 Image taskIcon = 334 Utilities.loadImage("org/netbeans/modules/tasklist/javaparser/import-sg.gif"); 336 s.setIcon(taskIcon); 337 s.setPriority(SuggestionPriority.HIGH); 338 tasks.add(s.getSuggestion()); 339 } 340 } 341 342 finder = getInsensitiveFinder(); 348 list = finder.findClasses(null, symbol, true); 350 if ((list != null) && (list.size() > 0)) { 351 Iterator itr = list.iterator(); 354 while (itr.hasNext()) { 355 final JCClass clz = (JCClass)itr.next(); 356 final String newClass = clz.getName(); 357 if (!newClass.equals(symbol)) { 358 final String oldClass = symbol; 360 String beforeDesc = 361 NbBundle.getMessage(ErrorSuggester.class, 362 "ReplaceClassConfirmation"); String afterDesc = 364 NbBundle.getMessage(ErrorSuggester.class, 365 "ReplaceClassAfter"); 367 SuggestionPerformer action = 368 new ReplaceSymbolPerformer( 369 lineNumber, 370 column, 371 line, 372 dobj, 373 doc, 374 oldClass, 375 newClass, 376 beforeDesc, 377 afterDesc, 378 clz, 379 false); 380 String sum = 381 NbBundle.getMessage(ErrorSuggester.class, 382 "ReplaceClassSg", oldClass, 384 newClass); SuggestionAgent s = 386 manager.createSuggestion(TYPE, 387 sum, 388 action, 389 this); 390 s.setLine(line); 391 Image taskIcon = Utilities.loadImage("org/netbeans/modules/tasklist/javaparser/import-sg.gif"); 393 s.setIcon(taskIcon); 394 s.setPriority(SuggestionPriority.HIGH); 395 tasks.add(s.getSuggestion()); 396 } 397 } 398 } 399 } else { 400 } 402 return; 403 } 404 405 final String symVar = "symbol : variable "; ix = summary.indexOf(symVar); 410 411 final String locClass = "location: class "; final String locInterface = "location: interface "; int lix = summary.indexOf(locClass); 414 if (lix != -1) { 415 lix += locClass.length(); 416 } else { 417 lix = summary.indexOf(locInterface); 418 if (lix != -1) { 419 lix += locInterface.length(); 420 } 421 } 422 423 if ((ix != -1) && (lix != -1)) { 424 ix += symVar.length(); 426 int eix = summary.indexOf(' ', ix); 427 if (eix != -1) { 428 String symbol = summary.substring(ix,eix); 429 String location = summary.substring(lix); 430 431 438 JCFinder finder = getSensitiveFinder(); 444 if (Character.isUpperCase(symbol.charAt(0))) { 445 List list = finder.findClasses(null, symbol, true); 448 if ((list != null) && (list.size() > 0)) { 449 Iterator itr = list.iterator(); 452 while (itr.hasNext()) { 453 final JCClass classname = (JCClass)itr.next(); 454 SuggestionPerformer action = 456 new ImportPerformer(lineNumber, 457 dobj, doc, 458 classname); 459 String fname = dobj.getPrimaryFile().getNameExt(); 460 String sum = NbBundle.getMessage(ErrorSuggester.class, 461 "ImportClassSg", classname, fname); SuggestionAgent s = 463 manager.createSuggestion(TYPE, 464 sum, 465 action, 466 this); 467 s.setLine(line); 468 Image taskIcon = 469 Utilities.loadImage("org/netbeans/modules/tasklist/javaparser/import-sg.gif"); 471 s.setIcon(taskIcon); 472 s.setPriority(SuggestionPriority.HIGH); 473 tasks.add(s.getSuggestion()); 474 } 475 } 476 } else { 477 JCClass clz = finder.getExactClass(location); 478 if (clz == null) { 479 return; 483 } 484 boolean staticOnly = false; boolean inspectOuterClasses = true; 486 List list = finder.findMethods(clz, symbol, true, 487 staticOnly, inspectOuterClasses); 488 if ((list != null) && (list.size() > 0)) { 489 Iterator itr = list.iterator(); 492 while (itr.hasNext()) { 493 494 497 final Object mtd = itr.next(); 498 final String var = symbol; 499 final String varAfter = var + "()"; 500 String beforeDesc = 501 NbBundle.getMessage(ErrorSuggester.class, 502 "ChangeMethodConfirmation"); String afterDesc = 504 NbBundle.getMessage(ErrorSuggester.class, 505 "ChangeMethodAfter"); SuggestionPerformer action = 507 new ReplaceSymbolPerformer( 508 lineNumber, 509 column, 510 line, 511 dobj, 512 doc, 513 var, 514 varAfter, 515 beforeDesc, 516 afterDesc, 517 null, 518 true); 519 String sum = 520 NbBundle.getMessage(ErrorSuggester.class, 521 "MakeMethodSg", var, varAfter); SuggestionAgent s = 523 manager.createSuggestion(TYPE, 524 sum, 525 action, 526 this); 527 s.setLine(line); 528 Image taskIcon = Utilities.loadImage("org/netbeans/modules/tasklist/javaparser/import-sg.gif"); 530 s.setIcon(taskIcon); 531 s.setPriority(SuggestionPriority.HIGH); 532 533 tasks.add(s.getSuggestion()); 534 } 535 } 536 } 537 } else { 538 } 540 } 541 542 543 544 final String symMet = "symbol : method "; ix = summary.indexOf(symMet); 548 549 560 561 if ((ix != -1) && (lix != -1)) { 562 ix += symMet.length(); 563 int eix = summary.indexOf(' ', ix); 564 if (eix != -1) { 565 String symbol = summary.substring(ix,eix); 566 String location = summary.substring(lix); 567 568 JCFinder finder = getInsensitiveFinder(); 574 JCClass clz = finder.getExactClass(location); 575 if (clz == null) { 576 suggestCreateMethod(symbol, summary, eix, location, tasks, lineNumber, column, dobj, manager); 580 return; 581 } 582 boolean staticOnly = false; boolean inspectOuterClasses = true; 584 585 586 if (symbol.equals("length")) { 589 JCFinder sfinder = getSensitiveFinder(); 590 List list = sfinder.findMethods(clz, "size", false, 591 staticOnly, inspectOuterClasses); 592 if ((list != null) && (list.size() > 0)) { 593 final String method = symbol; 594 final JCMethod mtd = (JCMethod)list.get(0); 595 final String newMethod = mtd.getName(); 596 597 createMethodReplaceSuggestion( 598 manager, tasks, doc, dobj, 599 line, lineNumber, 600 column, method, newMethod); 601 } 602 } else if (symbol.equals("size")) { 603 JCFinder sfinder = getSensitiveFinder(); 604 List list = sfinder.findMethods(clz, "length", false, 605 staticOnly, inspectOuterClasses); 606 if ((list != null) && (list.size() > 0)) { 607 final String method = symbol; 608 final JCMethod mtd = (JCMethod)list.get(0); 609 final String newMethod = mtd.getName(); 610 createMethodReplaceSuggestion( 611 manager, tasks, doc, dobj, line, 612 lineNumber, 613 column, method, newMethod); 614 } 615 } 616 617 List list = finder.findMethods(clz, symbol, false, 620 staticOnly, inspectOuterClasses); 621 if ((list != null) && (list.size() > 0)) { 622 List used = new ArrayList (list.size()); 625 Iterator itr = list.iterator(); 626 while (itr.hasNext()) { 627 final JCMethod mtd = (JCMethod)itr.next(); 628 final String newMethod = mtd.getName(); 629 if (newMethod.equals(symbol)) { 631 continue; 632 } 633 boolean alreadyUsed = false; 634 for (int k = 0; k < used.size(); k++) { 635 if (used.get(k).equals(newMethod)) { 639 alreadyUsed = true; 640 break; 641 } 642 } 643 if (alreadyUsed) { 644 continue; 645 } 646 used.add(newMethod); 647 648 final String method = symbol; 649 650 createMethodReplaceSuggestion( 651 manager, tasks, doc, dobj, line, 652 lineNumber, 653 column, method, newMethod); 654 } 655 } else { 656 suggestCreateMethod(symbol, summary, eix, location, tasks, lineNumber, column, dobj, manager); 657 } 658 } 659 } 660 } else if (summary.startsWith("incompatible types") && (column > 0)) { 662 681 685 686 final String foundStr = "found : "; int fix = summary.indexOf(foundStr); 688 final String reqStr = "required: "; int rix = summary.indexOf(reqStr); 690 if ((fix != -1) && (rix != -1)) { 691 fix += foundStr.length(); 692 rix += reqStr.length(); 693 int efix = summary.indexOf('\n', fix); 694 if (efix != -1) { 695 String found = summary.substring(fix, efix); 697 String req = summary.substring(rix); 698 702 705 column--; 707 String text = line.getText(); 708 if (column < text.length() && text.charAt(column) == '(') { 709 boolean fd = false; int i = column; 712 for (; i >= 0; i--) { 713 if (Character.isSpace(text.charAt(i))) { 714 fd = true; 715 break; 716 } else if (text.charAt(i) == '=') { 717 fd = true; 718 break; 719 } else if (text.charAt(i) == ')') { 720 break; 721 } 722 } 723 if (fd) { 724 if (i+1 < (column-1)) { 726 column = i+1; 727 } else { 728 int end = text.indexOf(')', column); 739 if (end != -1) { 740 createMethodReplaceSuggestion( 743 manager, tasks, doc, dobj, 744 line, lineNumber, 745 column, text.substring(column+1, end), 746 getClassName(req)); 747 } 748 return; 749 } 750 } else { 751 return; } 754 } 755 756 createCastSuggestion(manager, tasks, doc, dobj, line, 757 column, req); 758 } 759 } 760 } 761 } 762 763 private static String getClassName(String full) { 767 int n = full.length()-1; for (int i = 0; i < n; i++) { 770 if ((full.charAt(i) == '.') && 771 (Character.isUpperCase(full.charAt(i+1)))) { 772 return full.substring(i+1); 773 } 774 } 775 return full; 776 } 777 778 780 private void suggestCreateMethod(String symbol, String summary, int eix, 781 String location, List tasks, 782 int lineNumber, 783 int column, 784 DataObject dobj, 785 SuggestionManager manager) { 786 if (location.startsWith("java.") || 788 location.startsWith("javax.")) { 789 return; 792 } 793 794 FileObject f = null; 796 int div = location.lastIndexOf('.'); 797 if (div != -1) { 798 String pkg = location.substring(0, div); 800 String file = location.substring(div+1); 801 f = Repository.getDefault().find(pkg, file, "java"); 803 } else { 804 f = Repository.getDefault().find(".", location, "java"); 806 } 807 if (f == null) { 808 return; 809 } 810 DataObject obj = null; 811 try { 812 obj = DataObject.find(f); 813 } catch (Exception e) { 814 return; 815 } 816 817 int ix = summary.indexOf('(', eix); 819 String args = ""; 820 if (ix != -1) { 821 eix = summary.indexOf(')', ix); 822 args = summary.substring(ix+1, eix); 823 } 824 if (args.length() == 0) { 825 args = NbBundle.getMessage(ErrorSuggester.class, "NoArgs"); } 827 828 SourceCookie sc = null; 829 sc = (SourceCookie)obj.getCookie(SourceCookie.Editor.class); 830 if (sc == null) { 831 return; 832 } 833 834 boolean makePublic = (obj.getFolder() != dobj.getFolder()); SuggestionPerformer action = new CreateMethodPerformer(obj, 836 symbol, location, args, makePublic); 837 String sum = NbBundle.getMessage(ErrorSuggester.class, 838 "CreateMethod", symbol, location, args); 840 SuggestionAgent s = manager.createSuggestion(TYPE, sum, action, this); 841 s.setLine(TLUtils.getLineByNumber(dobj, lineNumber)); 842 Image taskIcon = Utilities.loadImage("org/netbeans/modules/tasklist/javaparser/import-sg.gif"); s.setIcon(taskIcon); 844 s.setPriority(SuggestionPriority.HIGH); 845 tasks.add(s.getSuggestion()); 846 } 847 848 private void createCastSuggestion( 849 SuggestionManager manager, List tasks, 850 final Document doc, 851 final DataObject dobj, 852 Line line, 853 int column, 854 String reqType) { 855 String beforeDesc = 856 NbBundle.getMessage(ErrorSuggester.class, 857 "CastConfirmation", reqType); String reqClass = getClassName(reqType); 859 SuggestionPerformer action = 860 new CastPerformer(column, 861 line, 862 dobj, 863 doc, 864 reqType, 865 reqClass, 866 beforeDesc); 867 868 String sum = NbBundle.getMessage(ErrorSuggester.class, 869 "AddCast", reqClass); SuggestionAgent s = 871 manager.createSuggestion(TYPE, 872 sum, 873 action, 874 this); 875 s.setLine(line); 876 Image taskIcon = Utilities.loadImage("org/netbeans/modules/tasklist/javaparser/import-sg.gif"); 878 s.setIcon(taskIcon); 879 s.setPriority(SuggestionPriority.HIGH); 880 881 tasks.add(s.getSuggestion()); 882 } 883 884 private void createMethodReplaceSuggestion( 885 SuggestionManager manager, List tasks, 886 final Document doc, 887 final DataObject dobj, 888 Line line, 889 int lineNumber, 890 int column, 891 String method, 892 String newMethod) { 893 String beforeDesc = 894 NbBundle.getMessage(ErrorSuggester.class, 895 "ReplaceMethodConfirmation"); String afterDesc = 897 NbBundle.getMessage(ErrorSuggester.class, 898 "ReplaceMethodAfter"); SuggestionPerformer action = 900 new ReplaceSymbolPerformer(lineNumber, 901 column, 902 line, 903 dobj, 904 doc, 905 method, 906 newMethod, 907 beforeDesc, 908 afterDesc, 909 null, 910 false); 911 912 String sum = NbBundle.getMessage(ErrorSuggester.class, 913 "ReplaceMethodSg", method, newMethod); SuggestionAgent s = 915 manager.createSuggestion(TYPE, 916 sum, 917 action, 918 this); 919 s.setLine(line); 920 Image taskIcon = Utilities.loadImage("org/netbeans/modules/tasklist/javaparser/import-sg.gif"); 922 s.setIcon(taskIcon); 923 s.setPriority(SuggestionPriority.HIGH); 924 925 tasks.add(s.getSuggestion()); 926 } 927 928 929 JCFinder getInsensitiveFinder() { 930 if (finderNoCase == null) { 931 finderNoCase = JCStorage.getStorage(). 932 935 getFinder(false, true, true); 937 } 938 return finderNoCase; 939 } 940 941 static JCFinder getSensitiveFinder() { 942 return JavaCompletion.getFinder(); 944 956 } 957 958 JCFinder finderNoCase = null; 959 JCFinder finderCase = null; 960 961 private ParserMessage[] getMessages(SuggestionContext env) { 962 if (env == this.env) { 964 return messages; 965 } else { 966 return null; 967 } 968 } 969 970 private ParserMessage[] messages = null; 971 972 973 public void objectParsed(Parsing.Event evt) { 974 if (env == null || (env.getFileObject().isValid() == false)) 976 return; 977 978 DataObject dataObject = null; 979 try { 980 dataObject = DataObject.find(env.getFileObject()); 981 } catch (IOException ex) { 982 ErrorManager.getDefault().notify(ex); 983 } 984 985 if (evt.getJavaDataObject() == dataObject) { 986 messages = evt.getMessages(); 987 errorsChanged(env); 988 } else { 989 991 } 1001 } 1002 1003 1004 private List showingTasks = null; 1005} 1006 1007 1008 | Popular Tags |