1 22 package org.aspectj.tools.ajdoc; 23 24 import org.aspectj.ajdoc.AdviceDoc; 25 import org.aspectj.ajdoc.AspectDoc; 26 import org.aspectj.ajdoc.PointcutDoc; 27 import org.aspectj.compiler.base.JavaCompiler; 28 import org.aspectj.compiler.base.ast.ASTObject; 29 30 import com.sun.javadoc.ClassDoc; 31 import com.sun.javadoc.ConstructorDoc; 32 import com.sun.javadoc.Doc; 33 import com.sun.javadoc.FieldDoc; 34 import com.sun.javadoc.MemberDoc; 35 import com.sun.javadoc.MethodDoc; 36 import com.sun.javadoc.PackageDoc; 37 import com.sun.javadoc.Parameter; 38 import com.sun.javadoc.SeeTag; 39 40 import java.io.PrintStream ; 41 import java.util.ArrayList ; 42 import java.util.List ; 43 import java.util.Locale ; 44 import java.util.StringTokenizer ; 45 46 51 public class SeeTagImpl extends TagImpl implements SeeTag { 52 62 63 64 private String packageName; 65 66 67 private String className; 68 69 70 private String memberName; 71 72 73 private PackageDoc packageDoc; 74 75 76 private ClassDoc classDoc; 77 78 79 private MemberDoc memberDoc; 80 81 82 private String label = ""; 83 84 85 private static JavaCompiler ajc = AjdocCompiler.instance(); 86 87 97 public SeeTagImpl(Doc doc, 98 String name, 99 String text, 100 Locale loc, 101 ErrPrinter err) { 102 super(doc, name, text, loc, err); 103 resolve(); 104 } 105 106 111 public String label() { 112 return label; 113 } 114 115 121 public String referencedPackageName() { 122 return packageName; 123 } 124 125 131 public PackageDoc referencedPackage() { 132 look(); 133 return packageDoc; 134 } 135 136 142 public String referencedClassName() { 143 return className; 144 } 145 146 152 public ClassDoc referencedClass() { 153 look(); 154 return classDoc; 155 } 156 157 164 public String referencedMemberName() { 165 return memberName; 166 } 167 168 174 public MemberDoc referencedMember() { 175 look(); 176 return memberDoc; 177 } 178 179 184 public String kind() { 185 return "@see"; 186 } 187 188 protected JavaCompiler ajc() { 189 if (ajc != null) { 190 return ajc; 191 } else if (doc() instanceof ASTObject) { 192 return ajc = ((ASTObject)doc()).getCompiler(); 193 } else if (doc() instanceof PackageDocImpl) { 194 return ajc = ((PackageDocImpl)doc()).ajc(); 195 } 196 return null; 197 } 198 199 void debugState(String m, PrintStream err) { 200 if (System.getProperty("seetag.debug") != null) { 201 if (null == err) err = System.err; 202 err.println("\t______________________ " + m 203 + "\n\tpackageName: "+packageName 204 + "\n\t packageDoc: " +packageDoc 205 + "\n\t className: " +className 206 + "\n\t classDoc: " +classDoc 207 + "\n\t memberName: " +memberName 208 + "\n\t memberDoc: " +memberDoc 209 + "\n\t label: " +label 210 ); 211 } 212 } 213 private boolean looked = false; 214 private void look() { 215 if (!looked) { 216 looked = true; 217 dolook(); 218 } 219 debugState("SeeTagImpl.look()", null); 220 } 221 222 private void dolook() { 223 224 if (className == null || className.length() < 1) { 227 classDoc = classDoc(doc()); 228 } else { 229 230 ClassDoc container = classDoc(doc()); 233 234 if (container == null) { 236 } else { 238 String fullName; 239 if (packageName == null || packageName.length() < 1) { 240 fullName = className; 241 } else { 242 fullName = packageName + '.' + className; 243 } 244 245 if (memberName != null && 253 memberName.indexOf('(') == -1) { 254 classDoc = container.findClass(fullName + '.' + memberName); 255 256 if (classDoc != null) { 258 memberName = null; 259 } 260 } 261 262 if (classDoc == null) { 265 classDoc = container.findClass(fullName); 266 } 267 } 268 } 269 270 if (classDoc != null) { 273 packageDoc = classDoc.containingPackage(); 274 } else if (packageName == null) { 275 276 if (classDoc == null && className != null && 280 className.indexOf('.') == -1) { 281 packageDoc = PackageDocImpl.getPackageDoc(className); 282 } 283 284 else if (classDoc != null) { 287 packageDoc = classDoc.containingPackage(); 288 } 289 290 else if (doc() instanceof PackageDoc) { 293 packageDoc = (PackageDoc)doc(); 294 } 295 } else { 296 297 packageDoc = PackageDocImpl.getPackageDoc(packageName != null 300 ? packageName 301 : ""); 302 } 303 304 if (memberName != null) { 306 lookForMember(memberName, (org.aspectj.ajdoc.ClassDoc)classDoc); 307 } 308 } 309 310 private void lookForMember(String spec, 311 org.aspectj.ajdoc.ClassDoc container) { 312 int ilparen = spec.indexOf('('); 313 String name; 314 315 if (ilparen == -1) { 321 name = spec; 322 if ((memberDoc = fieldDoc(name, container)) != null) { 323 return; 324 } 325 if ((memberDoc = methodDoc(name, container, null)) != null) { 326 return; 327 } 328 if ((memberDoc = pointcutDoc(name, container, null)) != null) { 329 return; 330 } 331 } else { 332 name = spec.substring(0, ilparen); 333 } 334 int irparen = spec.lastIndexOf(')'); 335 336 String paramsString; 338 if (irparen != -1) { 339 paramsString = spec.substring(ilparen+1, irparen); 340 } else { 341 paramsString = spec.substring(ilparen+1, spec.length()-1); 342 } 343 344 String [] paramNames = paramNames(paramsString); 346 347 if ((memberDoc = methodDoc(name, container, paramNames)) != null) { 353 return; 354 } 355 if ((memberDoc = constructorDoc(container, paramNames)) != null) { 356 return; 357 } 358 if ((memberDoc = pointcutDoc(name, container, paramNames)) != null) { 359 return; 360 } 361 if (container instanceof AspectDoc) { 362 if ((memberDoc = adviceDoc(name, 363 (AspectDoc)container, 364 paramNames)) != null) { 365 return; 366 } 367 } 368 } 369 370 private String [] paramNames(String restNoParens) { 371 if (restNoParens == null || restNoParens.length() == 0) { 372 return new String [0]; 373 } 374 List params = new ArrayList (); 375 for (StringTokenizer t = new StringTokenizer (restNoParens, ",", false); 376 t.hasMoreTokens();) { 377 String spec = t.nextToken().trim(); 378 int ispace = spec.indexOf(' '); 379 if (ispace != -1) { 380 spec = spec.substring(0, ispace); 381 } 382 params.add(spec); 383 } 384 return (String [])params.toArray(new String [params.size()]); 385 } 386 387 private FieldDoc fieldDoc(String name, ClassDoc container) { 388 for (ClassDoc cd = container; cd != null; cd = cd.superclass()) { 389 FieldDoc[] docs = cd.fields(); 390 for (int i = 0, N = docs.length; i < N; i++) { 391 if (docs[i].name().equals(name)) { 392 return docs[i]; 393 } 394 } 395 } 396 return null; 397 } 398 399 private PointcutDoc pointcutDoc(String name, 400 org.aspectj.ajdoc.ClassDoc container, 401 String [] paramNames) { 402 if (null == name) return null; 404 for (org.aspectj.ajdoc.ClassDoc cd = container; 405 cd != null; 406 cd = (org.aspectj.ajdoc.ClassDoc)cd.superclass()) { 407 PointcutDoc[] docs = cd.pointcuts(); 408 if (null == docs) { 409 continue; 410 } 411 for (int i = 0, N = docs.length; i < N; i++) { 412 PointcutDoc md = docs[i]; 413 if ((null != md) 414 && (name.equals(md.name())) 415 && ((null == paramNames) 416 || parametersMatch(md.parameters(), paramNames, container))) { 417 return md; 418 } 419 } 420 } 421 return null; 422 } 423 424 private MethodDoc methodDoc(String name, ClassDoc container, 425 String [] paramNames) { 426 for (ClassDoc cd = container; cd != null; cd = cd.superclass()) { 427 MethodDoc[] docs = cd.methods(); 428 for (int i = 0, N = docs.length; i < N; i++) { 429 MethodDoc md = docs[i]; 430 if (!md.name().equals(name)) { 431 continue; 432 } 433 if (paramNames == null) { 434 return md; 435 } else { 436 if (parametersMatch(md.parameters(), 437 paramNames, 438 container)) { 439 return md; 440 } 441 } 442 } 443 } 444 return null; 445 } 446 447 private ConstructorDoc constructorDoc(ClassDoc container, 448 String [] paramNames) { 449 for (ClassDoc cd = container; cd != null; cd = cd.superclass()) { 450 ConstructorDoc[] docs = cd.constructors(); 451 for (int i = 0, N = docs.length; i < N; i++) { 452 ConstructorDoc md = docs[i]; 453 if (paramNames == null) { 454 return md; 455 } else { 456 if (parametersMatch(md.parameters(), 457 paramNames, 458 container)) { 459 return md; 460 } 461 } 462 } 463 } 464 return null; 465 } 466 467 private AdviceDoc adviceDoc(String name, 468 AspectDoc container, 469 String [] paramNames) { 470 471 AspectDoc cd = container; 472 while (cd != null) { 473 AdviceDoc[] docs = cd.advice(); 474 for (int i = 0, N = docs.length; i < N; i++) { 475 AdviceDoc md = docs[i]; 476 if (!(name.equals(md.name()))) { 477 continue; 478 } 479 if (paramNames == null) { 480 return md; 481 } else { 482 if (parametersMatch(md.parameters(), 483 paramNames, 484 container)) { 485 return md; 486 } 487 } 488 } 489 Object o = cd.superclass(); 490 if (o instanceof AspectDoc) { 491 cd = (AspectDoc) o; 492 } else { 493 cd = null; 494 } 495 } 496 return null; 497 } 498 499 private boolean parametersMatch(Parameter[] params, 500 String [] paramNames, 501 ClassDoc container) { 502 if ((null == params) || (null == paramNames) || (null == container)) { 503 return false; 504 } 505 if (params.length != paramNames.length) { 506 return false; 507 } 508 for (int i = 0, N = params.length; i < N; i++) { 509 com.sun.javadoc.Type type1 = params[i].type(); 510 com.sun.javadoc.Type type2 = TypeImpl.getInstance(paramNames[i], 511 container); 512 if ((null == type1) || (!type1.equals(type2))) { 513 return false; 514 } 515 } 516 return true; 517 } 518 519 private ClassDoc classDoc(Doc d) { 520 if (d instanceof ClassDoc) { 521 return (ClassDoc)d; 522 } 523 if (d instanceof MemberDoc) { 524 return ((MemberDoc)d).containingClass(); 525 } 526 return null; 527 } 528 529 532 private static int findNextChar(final String s, final int start, final char x) { if ((null != s) && (start >= 0)) { 534 boolean escaped = false; 535 for (int i = start; i < s.length(); i++) { 536 char c = s.charAt(i); 537 if (('\\' == c) && !escaped) { 538 escaped = true; 539 continue; 540 } else if ((x == c) && !escaped) { 541 return i; 542 } 543 if (escaped) { 544 escaped = false; 545 } 546 } 547 } 548 return -1; 549 } 550 551 557 private void resolve() { 558 String str = text(); 559 560 if (str == null || str.length() < 1) { 561 return; 562 } 563 564 str = str.trim(); 565 566 int N = str.length(); 567 568 char first = str.charAt(0); 569 if (first == '<') { 570 if ((N < 4) || (str.charAt(N-1) != '>')) { 571 err().error("see_tag_unterminated_url",str); 572 } else { 573 char second = str.charAt(1); 574 if ((second == 'a') || (second == 'A')) { 575 label = str; 576 } else { 577 err().error("see_tag_unterminated_url",str); } 579 } 580 return; 581 } 582 583 if (first == '"') { 584 if (N == 1) { 585 err().error("see_tag_unterminated_string",str); 586 } else if (str.charAt(N-1) == '"') { 587 label = str; 588 } else { 589 int loc = findNextChar(str, 1, '"'); 590 if (-1 == loc) { 591 err().error("see_tag_unterminated_string",str); 592 } else { 593 label = str.substring(0, loc+1); 594 } 595 } 596 return; 597 } 598 char c = 0; 600 int state = 0, next = 0; 601 boolean finished = false; 602 603 int iclassEnd = -1; 604 int isharp = -1; 605 int ilastDot = -1; 606 int iStartLabel = -1; 607 int iEndMemberLabel = -1; boolean sharp = false; 609 int i; 610 done: 611 for (i = 0; i < N; i++, state = next) { 612 c = str.charAt(i); 613 switch (state) { 614 615 case 0: if (ident(c)) { next = 1; } 617 else if (c == '#') { next = 2; iclassEnd = i-1; } 618 else { 619 err().error("see_tag_dot_sharp_or_id","\""+c+"\"@0",str); 620 return; 621 } 622 break; 623 624 case 1: if (ident(c)) { next = 1; } 626 else if (c == '#') { next = 2; iclassEnd = i-1; } 627 else if (c == '.') { next = 3; ilastDot = i; } 628 else if (space(c)) { iclassEnd = i-1; next = 16; } 629 else { 630 err().error("see_tag_invalid_package_or_class","\""+c+"\"@1",str); 631 return; 632 } 633 break; 634 635 case 2: sharp = true; 637 if (ident(c)) { next = 4; isharp = i; } 638 else { 639 err().error("see_tag_expecting_field_name","\""+c+"\"@2",str); 640 return; 641 } 642 break; 643 644 case 3: if (ident(c)) { next = 1; } 646 else { 647 err().error("see_tag_invalid_id","\""+c+"\"@3",str); 648 return; 649 } 650 break; 651 652 case 4: if (ident(c)) { next = 4; } 654 else if (space(c)) { next = 13; iEndMemberLabel = i-1;} 655 else if (c == '(') { next = 15; } 656 else { 657 err().error("see_tag_invalid_param_start","\""+c+"\"@4",str); 658 return; 659 } 660 break; 661 662 case 5: if (ident(c)) { next = 6; } 664 else if (space(c)) { next = 5; } 665 else if (c == ')') { next = 13; iEndMemberLabel = i;} 666 else { 667 err().error("see_tag_premature_param_end","\""+c+"\"@5",str); 668 return; 669 } 670 break; 671 672 case 6: if (ident(c)) { next = 6; } 674 else if (c == '.') { next = 7; } 675 else if (c == '[') { next = 8; } 676 else if (space(c)) { next = 10; } 677 else if (c == ',') { next = 12; } 678 else if (c == ')') { iEndMemberLabel = i; next = 16; } 679 else { 680 err().error("see_tag_invalid_parameter_type","\""+c+"\"@6",str); 681 return; 682 } 683 break; 684 685 case 7: if (ident(c)) { next = 6; } 687 else { 688 err().error("see_tag_invalid_parameter_type_ident","\""+c+"\"@7",str); 689 return; 690 } 691 break; 692 693 case 8: if (c == ']') { next = 9; } 695 else if (space(c)) { next = 8; } 696 else { 697 err().error("see_tag_unterminated_array_type","\""+c+"\"@8",str); 698 return; 699 } 700 break; 701 702 case 9: if (c == '[') { next = 8; } 704 else if (space(c)) { next = 10; } 705 else if (c == ',') { next = 12; } 706 else if (c == ')') { iEndMemberLabel = i; next = 16; } 707 else { 708 err().error("see_tag_invalid_parameter_type","\""+c+"\"@9",str); 709 return; 710 } 711 break; 712 713 case 10: if (ident(c)) { next = 11; } 715 else if (space(c)) { next = 12; } 716 else if (c == ',') { next = 14; } 717 else if (c == ')') { iEndMemberLabel = i; next = 16; } 718 else { 719 err().error("see_tag_invalid_parameters","\""+c+"\"@10",str); 720 return; 721 } 722 break; 723 724 case 11: if (ident(c)) { next = 11; } 726 else if (space(c)) { next = 12; } 727 else if (c == ',') { next = 14; } 728 else if (c == ')') { iEndMemberLabel = i; next = 16; } 729 else { 730 err().error("see_tag_invalid_parameters","\""+c+"\"@11",str); 731 return; 732 } 733 break; 734 735 case 12: if (space(c)) { next = 12; } 737 else if (c == ',') { next = 14; } 738 else if (ident(c)) { next = 15; } 739 else if (c == ')') { iEndMemberLabel = i; next = 16; } 740 else { 741 err().error("see_tag_invalid_parameters","\""+c+"\"@12",str); 742 return; 743 } 744 break; 745 746 case 13: if (space(c)) { next = 13; } 748 else if (c == '(') { next = 5; } else if (ident(c)) { iStartLabel = i; next = 17; 751 } 752 else { 753 err().error("see_tag_invalid_parameters","\""+c+"\"@13",str); 754 return; 755 } 756 break; 757 758 case 14: if (ident(c)) { next = 6; } 760 else if (space(c)) { next = 14; } 761 else { 762 err().error("see_tag_expecting_typename_or_whitespace","\""+c+"\"@14",str); 763 return; 764 } 765 break; 766 767 case 15: if (ident(c)) { next = 6; } 769 else if (space(c)) { next = 15; } 770 else if (c == ')') { iEndMemberLabel = i; next = 16; } 771 else { 772 err().error("see_tag_premature_param_end","\""+c+"\"@15",str); 773 return; 774 } 775 break; 776 case 16 : if (ident(c)) { iStartLabel = i; next = 17; } 778 else if (space(c)) { next = 16; } 779 else { 780 String s = "\"" + c + "\" in \"" + text() + "\""; 781 err().error("see_tag_premature_param_end",s + "@16",str); 782 return; 783 } 784 break; 785 case 17 : if (ident(c)) { next = 17; } 787 else if (space(c)) { next = 17; } 788 else { 790 err().error("see_tag_premature_param_end","\""+c+"\"@17",str); 791 return; 792 } 793 break; 794 } 795 796 if (i == N-1) { 797 finished = next == -1 798 || next == 1 || next == 13 799 || next == 16 || next == 17 800 || next == 4 || next == 12; 801 } 802 803 } 804 805 if (sharp) { 806 if (ilastDot != -1) { 807 packageName = str.substring(0, ilastDot); 808 } 809 } else { 810 if (ilastDot == -1) { 811 } else { 813 packageName = str.substring(0, ilastDot); 814 } 815 } 816 817 if (sharp) { 818 if (iclassEnd != -1) { 819 if (ilastDot == -1) { 820 className = str.substring(0, iclassEnd+1); 821 } else { 822 className = str.substring(ilastDot+1, iclassEnd+1); 823 } 824 } 825 } else { 826 if (ilastDot == -1) { 827 if (iclassEnd != -1) { 828 className = str.substring(0, iclassEnd+1); 829 } else { 830 className = str; 831 } 832 } else { 833 if (iclassEnd != -1) { 834 className = str.substring(ilastDot+1, iclassEnd+1); 835 } else { 836 className = str.substring(ilastDot+1); 837 } 838 } 839 } 840 841 if (sharp) { 842 if (-1 != iEndMemberLabel) { 843 memberName = str.substring(isharp, iEndMemberLabel+1).trim(); 844 } else { 845 memberName = str.substring(isharp).trim(); 846 } 847 int parmLoc = memberName.indexOf("("); 849 if (-1 != parmLoc) { 850 int spaceLoc = memberName.indexOf(" "); 851 if ((-1 != spaceLoc) && (spaceLoc < parmLoc)) { 852 memberName = memberName.substring(0,spaceLoc) 853 + memberName.substring(parmLoc).trim(); 854 } 855 } 856 } 857 858 if (!finished) { 859 err().error("see_tag_prematurely_done",str); 860 } else { 861 if (iStartLabel != -1) { 862 label = str.substring(iStartLabel).trim(); 863 } else if (i < N-1) { label = str.substring(i).trim(); 865 } 866 } 867 } 868 869 String getPackageName() {return packageName;} 871 String getClassName() { return className;} 872 String getMemberName() { return memberName; } 873 String getLabel() { return label; } 874 } 875 | Popular Tags |