1 24 25 package org.aspectj.compiler.crosscuts; 26 import org.aspectj.compiler.crosscuts.ast.*; 27 import org.aspectj.compiler.base.ast.*; 28 import org.aspectj.compiler.base.cst.*; 29 import org.aspectj.compiler.base.parser.*; 30 import org.aspectj.compiler.base.JavaCompiler; 31 import org.aspectj.compiler.base.TypeManager; 32 33 import java.util.*; 34 import java.io.*; 35 36 public class AspectJParser extends JavaParser { 37 38 public AspectJParser(JavaCompiler compiler) { 39 super(compiler); 40 } 41 42 { 46 decParsers.put("aspect", new AspectDecParser()); 47 48 decParsers.put("pointcut", new PointcutDecParser()); 49 50 modifiers.put("privileged", new Integer (Modifiers.PRIVILEGED)); 51 } 52 53 54 protected Map aspectDecParsers = new HashMap(); 55 { 56 aspectDecParsers.put("declare", new DeclareParser()); 57 58 aspectDecParsers.put("before", new BeforeDecParser()); 59 aspectDecParsers.put("after", new AfterDecParser()); 60 aspectDecParsers.put("around", new AroundDecParser()); 61 62 aspectDecParsers.put("pointcut", new PointcutDecParser()); 64 } 65 66 protected void eatModifiersPattern() { 67 Token token; 68 while (true) { 69 token = peekToken(); 70 if (!(token.kind == BANG || isModifier(token))) break; 71 eatTopToken(); 72 } 73 } 74 75 public ModifiersPattern parseModifiersPattern(int legalModifiers) { 76 int trueValue = 0; 77 int falseValue = 0; 78 Token beginToken = peekToken(); 79 80 while (true) { 81 boolean assertion = true; 82 83 if (peekToken().kind == BANG) { 84 if (getModifier(peekToken(1)) == null) break; 85 eatTopToken(); 86 assertion = false; 87 } 88 89 Integer ivalue = getModifier(peekToken()); 90 if (ivalue == null) { 91 if (!assertion) { 92 throwError(null, "! in modifier pattern not followed by modifier"); 93 } 94 break; 95 } 96 97 int value = ivalue.intValue(); 98 if ((legalModifiers & value) != value) { 99 throwError(null, "illegal modifier for this dec"); 100 } 101 eatTopToken(); 102 if (assertion) trueValue |= value; 103 else falseValue |= value; 104 } 105 ModifiersPattern modifiers = new ModifiersPattern(dummySource,trueValue, falseValue); 106 addContext(modifiers, beginToken); 107 return modifiers; 108 } 109 110 public NameTypeDsPattern parseNameTypeDsPattern() { 111 if (peekToken(0).kind != BANG && !(isIdentifier(peekToken(0)))) { 112 return null; 113 } 114 115 TypeDs trueNames = new TypeDs(dummySource); 116 TypeDs falseNames = new TypeDs(dummySource); 117 118 while (true) { 119 Token token = peekToken(0); 120 boolean assertion = true; 121 if (token.kind == BANG) { 122 eatTopToken(); 123 token = peekToken(0); 124 assertion = false; 125 } 126 127 TypeD nameTypeD = parseNameTypeD(); 128 if (nameTypeD == null) { 129 if (!assertion) throwError(token, "illegal name pattern"); 130 } 131 132 if (assertion) { 133 trueNames.add(nameTypeD); 134 } else { 135 falseNames.add(nameTypeD); 136 } 137 if (peekToken(0).kind != COMMA) break; 138 eatTopToken(); 139 } 140 141 return new NameTypeDsPattern(dummySource,trueNames, falseNames); 142 } 143 144 public NameTypeDsPattern parseThrowsPattern() { 145 if (maybeEatKeyword("throws")) { 146 return parseNameTypeDsPattern(); 147 } else { 148 return null; 149 } 150 } 151 152 public GenTypeName parseFormalPattern() { 153 Token beginToken = peekToken(); 154 if (beginToken.kind == DOT && peekToken(1).kind == DOT) { 155 eatTopToken(); eatTopToken(); 156 return null; 158 } else { 159 GenTypeName genTypeName = parseGenTypeName(); 160 addContext(genTypeName, beginToken); 161 return genTypeName; 162 } 163 } 164 165 166 public FormalsPattern parseFormalsPattern() { 167 Token beginToken = peekToken(); 168 eatTopToken(LPAREN); 169 170 GenTypeNames names = new GenTypeNames(dummySource); 171 FormalsPattern formalsPattern = new FormalsPattern(dummySource,names); 173 if (peekToken().kind != RPAREN) { 174 while (true) { 175 GenTypeName pattern = parseFormalPattern(); 176 if (pattern == null) { 177 pattern = new EllipsesFakeTypeName(dummySource); 178 addContext(pattern, peekToken(-1)); 179 } 180 names.add(pattern); 181 182 Token t = popToken(); 183 if (t.kind == RPAREN) break; 184 else if (t.kind == COMMA) continue; 185 throwError(t, "expected ',' or ')'"); 186 } 187 } else { 188 eatTopToken(); 189 } 190 191 addContext(names, beginToken); 192 addContext(formalsPattern, beginToken); 193 return formalsPattern; 194 } 195 196 197 public Expr parseVarInitializer() { 198 if (peekToken(0).kind == ASSIGN) { 199 eatTopToken(); 200 if (peekToken(0).kind == LBRACE) { 201 return parseArrayInitializer(); 202 } else { 203 return parseExpr(); 204 } 205 } else { 206 return null; 207 } 208 } 209 210 public TypeD parseOptionalReturnTypeD() { 211 if (!maybeEatKeyword("returns")) return null; 212 213 Token beginToken = peekToken(); 214 return parseTypeD(); 215 } 216 217 public boolean isAdjacent(Token t1, Token t2) { 218 return t1.endPosition == t2.startPosition; 220 } 221 222 String makeNamePatternPiece(Token t) { 223 if (t.isIdentifier()) return t.image; 224 else if (t.kind == STAR) return "*"; 225 else if (t.kind == INTEGER_LITERAL) return t.image; 226 else return null; 228 } 229 230 public NamePattern parseNamePattern(Token t1, String firstPiece) { 231 List pieces = new ArrayList(); 232 pieces.add(firstPiece); 233 234 Token previousToken = t1; 235 while (isAdjacent(previousToken, peekToken())) { 236 previousToken = peekToken(); 237 String piece = makeNamePatternPiece(previousToken); 238 239 if (piece == null) break; 240 eatTopToken(); 241 pieces.add(piece); 242 } 243 244 if (pieces.size() == 1) { 245 String piece = (String )pieces.get(0); 246 if (piece == "*") { 247 return new AnyName(makeSourceLocation(t1)); 248 } else { 249 return new SimpleName(makeSourceLocation(t1), piece); 250 } 251 } else { 252 return new WildName(makeSourceLocation(t1), pieces); 253 } 254 } 255 public NamePattern parseNamePattern() { 256 Token t1 = peekToken(); 257 String firstPiece = makeNamePatternPiece(t1); 258 if (firstPiece == null) { 259 throwError(t1, "identifier pattern expected"); 260 return null; 261 } 262 eatTopToken(); 263 return parseNamePattern(t1, firstPiece); 264 } 265 266 protected boolean inAspect() { 267 if (peekEnclosingTypeDec() != null && peekEnclosingTypeDec() instanceof AspectDec) { 268 return true; 269 } 270 return false; 271 } 272 273 277 protected boolean eatIdentifier(boolean onlyDec) { 279 if (!inAspect() || !onlyDec) return super.eatIdentifier(onlyDec); 281 282 if (eatGenTypeName()) { 283 if (peekToken().kind == DOT) { 284 eatTopToken(); eatTopToken(); 285 } 286 return true; 287 } 288 return false; 289 } 290 291 292 static class TypeNameAndId { 293 public GenTypeName typeName; 294 public NamePattern namePattern; 295 296 public String getId() { 297 if (namePattern.getSimpleName() == null) { 298 namePattern.showError("identifier expected"); 299 } 300 return namePattern.getSimpleName(); 301 } 302 } 303 304 312 public TypeNameAndId parseTypeNameAndId() { 313 TypeNameAndId ret = new TypeNameAndId(); 314 Token beginToken = peekToken(); 315 316 if (peekToken().kind == LPAREN || peekKeyword("subtypes")) { 317 ret.typeName = parseGenTypeName(); 318 eatTopToken(DOT); 319 ret.namePattern = parseNamePattern(); 320 } else { 321 NamePatterns namePatterns = parseDottedNamePatterns(); 322 323 325 327 boolean includeSubTypes = false; 328 if (peekToken().kind == PLUS || peekToken().kind == LBRACKET) { 329 ret.typeName = finishParsingPatternTypeName(beginToken, namePatterns); 330 eatTopToken(DOT); 331 ret.namePattern = parseNamePattern(); 332 } else { 333 ret.namePattern = namePatterns.pop(); if (namePatterns.size() > 0) { 336 ret.typeName = new PatternTypeName(dummySource, namePatterns, false, 0); 337 ret.typeName.setSource(namePatterns); 338 } 339 } 340 } 341 342 return ret; 343 } 344 345 protected boolean eatGenTypeName() { 346 if (peekKeyword("import")) return false; 347 348 if (peekToken(0).kind == LPAREN && !(peekToken(1).kind == RPAREN)) { 350 parseGenTypeName(); 351 return true; 352 } else { 353 if (!eatTypeD()) return false; 354 maybeEatToken(PLUS); 355 return true; 356 } 357 } 358 359 360 protected Dec noDecFound() { 361 Token beginToken = peekToken(); 362 363 if (inAspect()) { 364 if (lookaheadIntroducedSuperDec()) { 365 return parseIntroducedSuperDec(); 366 } else if (lookaheadIntroducedConstructorDec()) { 367 return parseIntroducedConstructorDec(); 368 } 369 } 370 371 throwError(beginToken, "declaration or '}' expected"); 372 return null; 373 } 374 375 protected boolean lookaheadIntroducedSuperDec() { 376 pushCurrentIndex(); 377 378 if (eatGenTypeName()) { 379 if (maybeEatKeyword("implements") || maybeEatKeyword("extends")) { 380 throwError(peekToken(-1), "expected +implements or +extends"); 381 return false; 382 } else if (this.maybeEatToken(PLUS) && 383 (maybeEatKeyword("implements") || maybeEatKeyword("extends"))) 384 { 385 popCurrentIndex(); 386 return true; 387 } 388 } 389 popCurrentIndex(); 390 return false; 391 } 392 393 public Dec parseIntroducedSuperDec() { 394 getCompiler().warnVersion("1.0alpha1", tokenToASTObject(peekToken()), 395 "use declare parents instead"); 396 397 GenTypeName typeName = parseGenTypeName(); 398 eatTopToken(PLUS); 399 boolean isImplements; 400 if (maybeEatKeyword("implements")) { 401 isImplements = true; 402 } else { 403 eatKeyword("extends"); 404 isImplements = false; 405 } 406 TypeDs typeDs = parseTypeDs(); 407 Dec ret = new IntroducedSuperDec(dummySource, typeName, typeDs, isImplements); 408 eatTopToken(SEMICOLON); 409 return ret; 410 } 411 412 413 protected boolean lookaheadIntroducedConstructorDec() { 414 pushCurrentIndex(); 415 416 this.eatModifiers(); 417 if (this.eatGenTypeName() && maybeEatToken(DOT) && maybeEatToken(NEW)) { 420 popCurrentIndex(); 421 return true; 422 } 423 424 popCurrentIndex(); 425 return false; 426 } 427 428 429 430 431 public Dec parseIntroducedConstructorDec() { 432 int legalModifiers = Modifiers.PUBLIC | Modifiers.PROTECTED | Modifiers.PRIVATE; 433 434 Token beginToken = peekToken(); 435 Modifiers modifiers = parseModifiers(legalModifiers); 436 GenTypeName genTypeName = null; 437 if (inAspect()) { 438 TypeNameAndId gid = parseTypeNameAndId(); 439 genTypeName = gid.typeName; 440 String id = gid.getId(); 441 if (genTypeName != null) { 442 if (!id.equals("new")) { 443 throwError(beginToken, "bad introduced constructor syntax"); 444 } 445 } else { 446 if (!id.equals(peekEnclosingTypeDec().getId())) { 447 throwError(beginToken, "constructor name doesn't match enclosing type " + 448 peekEnclosingTypeDec().getId()); 449 } 450 } 451 } else { 452 parseIdMatchingEnclosingTypeName("constructor name"); 453 } 454 455 456 Formals formals = parseFormals(); 457 TypeDs _throws = parseThrows(); 458 459 Dec ret = new ConstructorDec(dummySource,modifiers, formals, _throws, 460 parseConstructorBody()); 461 462 if (genTypeName != null) { 463 return new IntroducedDec(dummySource, genTypeName, ret); 465 } else { 466 return ret; 467 } 468 } 469 470 public Dec parseConstructorDec() { 471 pushCurrentIndex(); 472 eatModifiers(); 473 if (peekKeyword("subtypes")) { 474 popCurrentIndex(); 475 return parseIntroducedConstructorDec(); 476 } else { 477 popCurrentIndex(); 478 return super.parseConstructorDec(); 479 } 480 } 481 482 public Dec parseMethodDec() { 483 int legalModifiers; 484 if (inInterface) { 485 legalModifiers = Modifiers.PUBLIC | Modifiers.ABSTRACT; 486 } else { 487 legalModifiers = Modifiers.PUBLIC | Modifiers.PROTECTED | Modifiers.PRIVATE | 488 Modifiers.ABSTRACT | Modifiers.STATIC | Modifiers.FINAL | 489 Modifiers.SYNCHRONIZED | Modifiers.NATIVE | Modifiers.STRICT; 490 } 491 492 Modifiers modifiers = parseModifiers(legalModifiers); 493 if (inInterface) { 494 modifiers.setAbstract(true); 495 modifiers.setPublic(true); 496 } 497 498 TypeD typeD = parseTypeD(); 499 500 GenTypeName genTypeName = null; 501 String id = null; 502 if (inAspect()) { 503 TypeNameAndId gid = parseTypeNameAndId(); 504 genTypeName = gid.typeName; 505 id = gid.getId(); 506 if (genTypeName == null && id.equals("around")) { 508 return parseAroundAdviceDec(modifiers, typeD); 509 } 510 } else { 511 id = parseId(); 512 } 513 514 Formals formals = parseFormals(); 515 516 typeD = addBracketsToTypeD(typeD); 518 519 TypeDs _throws = parseThrows(); 520 521 MethodDec ret = new MethodDec(dummySource, modifiers, typeD, id, formals, _throws, 522 parseOptionalCodeBody()); 523 524 if (genTypeName != null) { 525 return new IntroducedDec(dummySource, genTypeName, ret); 527 } else { 528 return ret; 529 } 530 } 531 532 533 public Stmt parseFieldDec() { 534 int legalModifiers; 535 536 if (inInterface) { 537 legalModifiers = Modifiers.PUBLIC | Modifiers.STATIC | Modifiers.FINAL; 538 } else { 539 legalModifiers = Modifiers.PUBLIC | Modifiers.PROTECTED | Modifiers.PRIVATE | 540 Modifiers.STATIC | Modifiers.FINAL | 541 Modifiers.TRANSIENT | Modifiers.VOLATILE; 542 } 543 544 Token beginToken = peekToken(); 545 Modifiers modifiers = parseModifiers(legalModifiers); 546 547 if (inInterface) { 548 modifiers.setPublic(true); 549 modifiers.setStatic(true); 550 modifiers.setFinal(true); 551 } 552 553 TypeD baseTypeD = parseTypeD(); 554 555 Decs decs = null; 556 Dec dec = null; 557 558 while (true) { 559 GenTypeName genTypeName = null; 560 String id = null; 561 if (inAspect()) { 562 TypeNameAndId gid = parseTypeNameAndId(); 563 genTypeName = gid.typeName; 564 id = gid.getId(); 565 } else { 566 id = parseId(); 567 } 568 TypeD typeD = baseTypeD; 569 570 Expr initializer = null; 571 typeD = addBracketsToTypeD(typeD); 572 576 Token endToken = popToken(); 577 if (endToken.kind == ASSIGN) { 578 if (typeD instanceof ArrayTypeD && peekToken().kind == LBRACE) { 579 initializer = parseArrayInitializer(); 580 } else { 581 initializer = parseExpr(); 582 } 583 endToken = popToken(); 584 } 585 586 dec = new FieldDec(dummySource,(Modifiers)modifiers.copy(), typeD, id, initializer); 587 addContext(dec, beginToken); 588 if (genTypeName != null) { 589 dec = new IntroducedDec(dummySource, genTypeName, dec); 590 } 591 592 if (endToken.kind == SEMICOLON) { 593 if (decs != null) decs.add(dec); 594 break; 595 } else if (endToken.kind == COMMA) { 596 if (decs == null) decs = new Decs(dummySource,dec); 597 else decs.add(dec); 598 599 baseTypeD = (TypeD)baseTypeD.copy(); 601 continue; 602 } else { 603 throwError(endToken, "expected ',' or ';'"); 604 } 605 } 606 607 if (decs != null) return decs; 608 else return dec; 609 } 610 611 612 613 614 615 public ConstructorPattern parseConstructorPattern() { 619 int legalModifiers = Modifiers.PUBLIC | Modifiers.PROTECTED | Modifiers.PRIVATE 620 | Modifiers.STRICT; 622 Token beginToken = peekToken(); 623 Modifiers modifiers = parseModifiersPattern(legalModifiers); 624 625 TypeNameAndId gid = parseTypeNameAndId(); 626 GenTypeName declaringType = gid.typeName; 627 628 630 if (!"new".equals(gid.namePattern.getSimpleName())) { 631 this.throwError(peekToken(-1), "expected new"); 632 } 633 FormalsPattern formals = parseFormalsPattern(); 634 NameTypeDsPattern _throws = parseThrowsPattern(); 635 636 ConstructorPattern ret = new ConstructorPattern(dummySource,modifiers, declaringType, formals, _throws); 637 addContext(ret, beginToken); 638 return ret; 639 } 640 641 public MethodPattern parseMethodPattern() { 642 int legalModifiers = Modifiers.PUBLIC | Modifiers.PROTECTED | Modifiers.PRIVATE | 643 Modifiers.ABSTRACT | Modifiers.STATIC | Modifiers.FINAL | 644 Modifiers.SYNCHRONIZED | Modifiers.NATIVE | Modifiers.STRICT; 645 646 Token beginToken = peekToken(); 647 Modifiers modifiers = parseModifiersPattern(legalModifiers); 648 GenTypeName returnType = parseGenTypeName(); 649 650 TypeNameAndId gid = parseTypeNameAndId(); 651 GenTypeName declaringType = gid.typeName; 652 NamePattern id = gid.namePattern; 653 if ("new".equals(id.getSimpleName())) { 654 this.tokenToASTObject(beginToken).showError("constructor patterns don't have a return type"); 655 } 656 657 FormalsPattern formals = parseFormalsPattern(); 658 NameTypeDsPattern _throws = parseThrowsPattern(); 659 660 MethodPattern ret = new MethodPattern(dummySource,modifiers, declaringType, returnType, id, formals, _throws); 661 addContext(ret, beginToken); 662 return ret; 663 } 664 665 public CodePattern parseConstructorOrMethodPattern() { 666 pushCurrentIndex(); 669 try { 670 CodePattern ret = parseConstructorPattern(); 671 return ret; 674 } catch (ParseException pe) { 675 popCurrentIndex(); 676 return parseMethodPattern(); 677 } 678 } 679 680 public FieldPattern parseFieldPattern() { 681 int legalModifiers = Modifiers.PUBLIC | Modifiers.PROTECTED | Modifiers.PRIVATE | 682 Modifiers.STATIC | Modifiers.FINAL | 683 Modifiers.NATIVE | Modifiers.TRANSIENT; 684 685 Token beginToken = peekToken(); 686 Modifiers modifiers = parseModifiersPattern(legalModifiers); 687 GenTypeName fieldType = parseGenTypeName(); 688 689 TypeNameAndId gid = parseTypeNameAndId(); 690 GenTypeName declaringType = gid.typeName; 691 NamePattern id = gid.namePattern; 692 696 FieldPattern ret = new FieldPattern(dummySource,modifiers, declaringType, fieldType, id); 697 addContext(ret, beginToken); 698 return ret; 699 } 700 701 720 public void skipToMatching(int lparen, int rparen, int depth) { 721 do { 722 Token t = popToken(); 723 if (t.kind == lparen) depth++; 724 if (t.kind == rparen) depth--; 725 } while (depth > 0); 726 } 727 728 729 public void skipToMatchingParen() { 730 skipToMatching(LPAREN, RPAREN, 0); 731 } 732 733 public void warnNameChange(String name, String newName) { 734 if (name.equals(newName)) return; 735 736 getCompiler().warnVersion("1.0alpha1", tokenToASTObject(peekToken(-1)), 737 "change from " + name + " to " + newName + ""); 738 } 739 740 public Pcd parseFunctionPcd() { 741 parseNoModifiers(); 742 Token beginToken = peekToken(); 743 String name = parseAnyId(); 744 745 if (name.equals("receptions")) { 746 getCompiler().errorVersion("1.0alpha1", tokenToASTObject(peekToken(-1)), 747 "replaced by call, see release notes"); 748 skipToMatchingParen(); 749 return new EmptyPcd(dummySource); 750 } else if (name.equals("calls") || name.equals("call")) { 751 warnNameChange(name, "call"); 752 753 eatTopToken(LPAREN); 754 CodePattern codePattern = parseConstructorOrMethodPattern(); 755 eatTopToken(RPAREN); 756 return new CallPcd(dummySource, codePattern); } else if (name.equals("gets") || name.equals("get")) { 758 warnNameChange(name, "get"); 759 eatTopToken(LPAREN); 760 FieldPattern fieldPattern = parseFieldPattern(); 761 eatTopToken(RPAREN); 762 if (maybeEatToken(LBRACKET)) { 763 getCompiler().errorVersion("1.0alpha1", tokenToASTObject(peekToken(-1)), 764 "[oldValue] not supported use field access to get this value"); 765 skipToMatching(LBRACKET, RBRACKET, 1); 766 } 767 return new FieldGetPcd(dummySource,fieldPattern); } else if (name.equals("sets") || name.equals("set")) { 769 warnNameChange(name, "set"); 770 eatTopToken(LPAREN); 771 FieldPattern fieldPattern = parseFieldPattern(); 772 eatTopToken(RPAREN); 773 774 if (maybeEatToken(LBRACKET)) { 775 getCompiler().errorVersion("1.0alpha1", tokenToASTObject(peekToken(-1)), 776 "[oldValue][newValue] not supported use field access to get oldValue and args(newValue)"); 777 skipToMatching(LBRACKET, RBRACKET, 1); 778 skipToMatching(LBRACKET, RBRACKET, 0); 779 } 780 return new FieldSetPcd(dummySource,fieldPattern); } else if (name.equals("executions") || name.equals("execution")) { 782 warnNameChange(name, "execution"); 783 eatTopToken(LPAREN); 784 CodePattern codePattern = parseConstructorOrMethodPattern(); 785 eatTopToken(RPAREN); 786 return new ExecutionPcd(dummySource,codePattern); 787 } else if (name.equals("initialization")) { 788 eatTopToken(LPAREN); 789 ConstructorPattern codePattern = parseConstructorPattern(); 790 eatTopToken(RPAREN); 791 return new InitializerPcd(dummySource, codePattern); 792 } else if (name.equals("initializations")) { 793 getCompiler().errorVersion("1.0alpha1", tokenToASTObject(peekToken(-1)), 794 "replaced by initialization with different meaning, see release notes"); 795 skipToMatchingParen(); 796 return new EmptyPcd(dummySource); 797 } else if (name.equals("staticinitializations") || name.equals("staticinitialization")) { 798 warnNameChange(name, "staticinitialization"); 799 eatTopToken(LPAREN); 800 GenTypeName genTypeName = parseGenTypeName(); 801 eatTopToken(RPAREN); 802 return new StaticInitializerPcd(dummySource,genTypeName); 803 } else if (name.equals("handlers") || name.equals("handler")) { 804 warnNameChange(name, "handler"); 805 eatTopToken(LPAREN); 806 GenTypeName genTypeName = parseGenTypeName(); 807 eatTopToken(RPAREN); 808 return new HandlerPcd(dummySource,genTypeName); 809 } else if (name.equals("hasaspect")) { 810 getCompiler().errorVersion("1.0alpha1", tokenToASTObject(peekToken(-1)), 811 "change to if(A.hasAspect(o))"); 812 eatTopToken(LPAREN); 813 GenTypeName genTypeName = parseGenTypeName(); 814 eatTopToken(RPAREN); 815 return new EmptyPcd(dummySource); 816 } else if (name.equals("instanceof") || name.equals("this")) { 817 warnNameChange(name, "this"); 818 eatTopToken(LPAREN); 819 GenTypeName genTypeName = parseGenTypeName(); 820 eatTopToken(RPAREN); 821 return new ThisPcd(dummySource,genTypeName); 822 } else if (name.equals("within")) { 823 eatTopToken(LPAREN); 824 GenTypeName genTypeName = parseGenTypeName(); 825 eatTopToken(RPAREN); 826 return new WithinPcd(dummySource,genTypeName); 827 } else if (name.equals("target")) { 828 eatTopToken(LPAREN); 829 GenTypeName genTypeName = parseGenTypeName(); 830 eatTopToken(RPAREN); 831 return new TargetPcd(dummySource,genTypeName); 832 } else if (name.equals("args")) { 833 FormalsPattern genTypeNames = parseFormalsPattern(); 835 return new ArgsPcd(dummySource,genTypeNames); 837 } else if (name.equals("withinall")) { 838 getCompiler().errorVersion("1.0alpha1", tokenToASTObject(peekToken(-1)), 839 "replaced with with(T+)"); 840 eatTopToken(LPAREN); 841 GenTypeName genTypeName = parseGenTypeName(); 842 CodePattern codePattern = null; 843 eatTopToken(RPAREN); 844 return new EmptyPcd(dummySource); 845 } else if (name.equals("withincode")) { 846 eatTopToken(LPAREN); 847 CodePattern codePattern = parseConstructorOrMethodPattern(); 848 eatTopToken(RPAREN); 849 return new WithinCodePcd(dummySource,codePattern); 850 } else if (name.equals("callsto")) { 851 getCompiler().errorVersion("1.0alpha1", tokenToASTObject(peekToken(-1)), 852 "not supported any more due to the removal of reception join points"); 853 skipToMatchingParen(); 854 return new EmptyPcd(dummySource); 855 } else if (name.equals("cflow")) { 856 eatTopToken(LPAREN); 857 Pcd pointcut = parsePcd(); 858 eatTopToken(RPAREN); 859 return new CFlowPcd(dummySource,pointcut, true); 860 } else if (name.equals("if")) { 861 eatTopToken(LPAREN); 862 Expr test = parseExpr(); 863 eatTopToken(RPAREN); 864 return new IfPcd(dummySource, test); 865 } else if (name.equals("cflowbelow")) { 866 eatTopToken(LPAREN); 867 Pcd pointcut = parsePcd(); 868 eatTopToken(RPAREN); 869 return new CFlowPcd(dummySource,pointcut, false); 870 } else if (name.equals("cflowtop")) { 871 getCompiler().warnVersion("0.8beta3", tokenToASTObject(peekToken(-1)), 872 "use common idiom cflow(P && !cflowbelow(P))"); 873 return new EmptyPcd(dummySource); 874 } else { 875 return new NamePcd(dummySource,null, name, parseFormalsPattern(), null); 876 } 877 } 878 879 private TypeD typeDFromName(Name name) { 880 UnresolvedNameTypeD ret = new UnresolvedNameTypeD(dummySource,name); 881 ret.setSource(name); 882 return ret; 883 } 884 885 886 private NamePcd parseNamePcd() { 887 Token begin = peekToken(); 888 Name name = parseExtendedName(); 889 if (name == null) { 890 throwError(begin, "expected pcd here"); 891 } 892 893 String pointcutName = name.getId(); 894 895 TypeD inTypeD = null; 896 if (name.getParentName() != null) { 897 inTypeD = typeDFromName(name.getParentName()); 898 } 899 FormalsPattern formals = parseFormalsPattern(); 900 return new NamePcd(dummySource,inTypeD, pointcutName, formals, null); 901 } 902 903 public Pcd parsePcdTerminal() { 904 if (peekToken(1).kind == DOT) { 905 return parseNamePcd(); 906 } else { 907 return parseFunctionPcd(); 908 } 909 } 910 911 912 class PcdOp extends PrefixOperator { 913 public PcdOp(int kind) { 914 super(kind, -1); 915 } 916 917 public Expr parse() { 918 return parsePcdTerminal(); 919 } 920 } 921 922 class UnionPcdOperator extends InfixOperator { 923 public UnionPcdOperator(int precedence) { 924 super("||", precedence); 925 } 926 927 public Expr parse(Expr lhs) { 928 Pcd rhsCC = (Pcd)parentParse(precedence); 929 return new OrPcd(dummySource,(Pcd)lhs, rhsCC); 930 } 931 } 932 933 class IntersectPcdOperator extends InfixOperator { 934 public IntersectPcdOperator(int precedence) { 935 super("&&", precedence); 936 } 937 938 public Expr parse(Expr lhs) { 939 Pcd rhsCC = (Pcd)parentParse(precedence); 940 return new AndPcd(dummySource,(Pcd)lhs, rhsCC); 941 } 942 } 943 944 class ComplementPcdOperator extends PrefixOperator { 945 public ComplementPcdOperator(int precedence) { 946 super("!", precedence); 947 } 948 949 public Expr parse() { 950 if (isModifier(peekToken(1))) { 953 return parsePcdTerminal(); 954 } 955 956 eatTopToken(); return new NotPcd(dummySource,(Pcd)parentParse(precedence)); 958 } 959 } 960 961 class ParenPcdOperator extends PrefixOperator { 962 public ParenPcdOperator(int precedence) { 963 super("(", precedence); 964 } 965 966 public Expr parse() { 967 eatTopToken(); Pcd cc = (Pcd)parentParse(precedence); 969 eatTopToken(RPAREN); 970 return cc; 971 } 972 } 973 974 private InfixOperator[] infixPcdOperators = { 975 new UnionPcdOperator(500), 976 new IntersectPcdOperator(700), 977 }; 978 979 private PrefixOperator[] prefixPcdOperators = { 980 new PcdOp(IDENTIFIER), 981 new PcdOp(STAR), 982 new PcdOp(NEW), 983 new ComplementPcdOperator(3000), 984 new ParenPcdOperator(1), 985 }; 986 987 988 protected ExprParser pointcutParser = 989 new ExprParser(prefixPcdOperators, infixPcdOperators, false); 990 991 public Pcd parsePcd() { 992 Pcd ret; 993 ret = (Pcd)pointcutParser.parse(); 994 if (ret == null) { 995 throwError(null, "pointcut designator required"); 996 } 997 return ret; 998 } 999 1000 1001 class TypeNameOp extends PrefixOperator { 1002 public TypeNameOp(int kind) { 1003 super(kind, -1); 1004 } 1005 1006 public Expr parse() { 1007 return parseTypeNameTerminal(); 1008 } 1009 } 1010 1011 class UnionTypeNameOperator extends InfixOperator { 1012 public UnionTypeNameOperator(int precedence) { 1013 super("||", precedence); 1014 } 1015 1016 public Expr parse(Expr lhs) { 1017 GenTypeName rhsCC = (GenTypeName)parentParse(precedence); 1018 return new UnionTypeName(dummySource,(GenTypeName)lhs, rhsCC); 1019 } 1020 } 1021 1022 class IntersectTypeNameOperator extends InfixOperator { 1023 public IntersectTypeNameOperator(int precedence) { 1024 super("&&", precedence); 1025 } 1026 1027 public Expr parse(Expr lhs) { 1028 GenTypeName rhsCC = (GenTypeName)parentParse(precedence); 1029 return new IntersectTypeName(dummySource,(GenTypeName)lhs, rhsCC); 1030 } 1031 } 1032 1033 class ComplementTypeNameOperator extends PrefixOperator { 1034 public ComplementTypeNameOperator(int precedence) { 1035 super("!", precedence); 1036 } 1037 1038 public Expr parse() { 1039 eatTopToken(); return new ComplementTypeName(dummySource,(GenTypeName)parentParse(precedence)); 1041 } 1042 } 1043 1044 class ParenTypeNameOperator extends PrefixOperator { 1045 public ParenTypeNameOperator(int precedence) { 1046 super("(", precedence); 1047 } 1048 1049 public Expr parse() { 1050 eatTopToken(); GenTypeName cc = (GenTypeName)parentParse(precedence); 1052 eatTopToken(RPAREN); 1053 return cc; 1054 } 1055 } 1056 1057 private InfixOperator[] infixTypeNameOperators = { 1058 new UnionTypeNameOperator(500), 1059 new IntersectTypeNameOperator(700), 1060 }; 1061 1062 private PrefixOperator[] prefixTypeNameOperators = { 1063 new TypeNameOp(IDENTIFIER), 1064 new TypeNameOp(STAR), 1065 new ComplementTypeNameOperator(3000), 1066 new ParenTypeNameOperator(1), 1067 }; 1068 1069 1070 protected ExprParser typeNameParser = 1071 new ExprParser(prefixTypeNameOperators, infixTypeNameOperators, false); 1072 1073 1074 public GenTypeName parseGenTypeName() { 1075 GenTypeName ret = (GenTypeName)typeNameParser.parse(); 1076 if (ret == null) { 1077 throwError(peekToken(), "expected type name"); 1078 } 1079 return ret; 1080 } 1081 1082 public GenTypeName parseTypeNameTerminal() { 1083 Token beginToken = peekToken(); 1084 1085 if (maybeEatKeyword("subtypes")) { 1086 getCompiler().errorVersion("1.0alpha1", tokenToASTObject(peekToken(-1)), 1087 "subtypes(T) should be replaced by T+"); 1088 skipToMatchingParen(); 1089 return null; 1090 } 1091 1092 GenTypeName baseType = parsePatternTypeName(); 1093 1108 return baseType; 1112 } 1113 1114 public GenTypeName parsePatternTypeName() { 1115 Token beginToken = peekToken(); 1116 NamePatterns names = parseDottedNamePatterns(); 1117 1118 return finishParsingPatternTypeName(beginToken, names); 1119 } 1120 1121 protected PatternTypeName finishParsingPatternTypeName(Token beginToken, NamePatterns names) { 1122 boolean includeSubTypes = false; 1123 if (maybeEatToken(PLUS)) includeSubTypes = true; 1124 1125 int dimensions = 0; 1126 while (peekToken().kind == LBRACKET && peekToken(1).kind == RBRACKET) { 1127 eatTopToken(); eatTopToken(); 1128 dimensions += 1; 1129 } 1130 1131 PatternTypeName ret = new PatternTypeName(dummySource, names, includeSubTypes, dimensions); 1132 addContext(ret, beginToken); 1133 return ret; 1134 } 1135 1136 1139 public NamePatterns parseDottedNamePatterns() { 1140 Token beginToken = peekToken(); 1141 1142 NamePatterns ret = new NamePatterns(dummySource,parseNamePattern()); 1143 1144 String extraName = null; 1145 while (peekToken().kind == DOT || peekToken().kind == FLOATING_POINT_LITERAL) { 1146 Token t = popToken(); 1147 if (t.kind == FLOATING_POINT_LITERAL) { 1148 String i = t.image; 1149 int dot = i.indexOf('.'); 1150 NamePattern p = ret.get(ret.size()-1); 1151 if (p instanceof AnyName) { 1152 List pieces = new ArrayList(); 1153 pieces.add("*"); 1154 pieces.add(i.substring(0, dot)); 1155 p.replaceWith(new WildName(dummySource, pieces)); 1156 } else { 1157 ((WildName)p).getPieces().add(i.substring(0, dot)); 1158 } 1159 if (dot != i.length()-1) { 1160 extraName = i.substring(dot+1); 1161 } 1162 } 1163 if (extraName == null && maybeEatToken(DOT)) { 1164 ret.add(new EllipsesFakeNamePattern(dummySource)); 1165 } 1166 if (extraName != null) { 1167 ret.add(parseNamePattern(t, extraName)); 1168 extraName = null; 1169 } else { 1170 ret.add(parseNamePattern()); 1171 } 1172 } 1173 1174 addContext(ret, beginToken); 1175 return ret; 1176 } 1177 1178 1179 1180 public PerClause parsePerClause() { 1181 PerClause ret = null; 1182 Token beginToken = peekToken(); 1183 1184 if (!beginToken.isIdentifier()) return null; 1185 1186 String name = parseAnyId(); 1187 if (name.equals("perthis")) { 1188 eatTopToken(LPAREN); 1189 Pcd pointcut = parsePcd(); 1190 eatTopToken(RPAREN); 1191 ret = new PerThisOrTarget(dummySource,pointcut, true); 1193 } else if (name.equals("pertarget")) { 1194 eatTopToken(LPAREN); 1195 Pcd pointcut = parsePcd(); 1196 eatTopToken(RPAREN); 1197 ret = new PerThisOrTarget(dummySource,pointcut, false); 1199 } else if (name.equals("percflow")) { 1200 eatTopToken(LPAREN); 1201 Pcd pointcut = parsePcd(); 1202 eatTopToken(RPAREN); 1203 ret = new PerCFlow(dummySource,pointcut, true); 1204 } else if (name.equals("percflowbelow")) { 1205 eatTopToken(LPAREN); 1206 Pcd pointcut = parsePcd(); 1207 eatTopToken(RPAREN); 1208 ret = new PerCFlow(dummySource,pointcut, false); 1209 } else if (name.equals("issingleton")) { 1210 eatTopToken(LPAREN); 1211 eatTopToken(RPAREN); 1212 ret = new PerSingleton(dummySource); 1213 } else { 1214 throwError(beginToken, 1215 "expected issingleton, pertarget, perthis, percflow or percflowbelow"); 1216 } 1217 1218 addContext(ret, beginToken); 1219 return ret; 1220 } 1221 1222 public PerClause parseOldOfClause() { 1223 PerClause ret = null; 1224 Token beginToken = peekToken(-1); 1225 1226 String name = parseAnyId(); 1227 if (name.equals("eachobject")) { 1228 getCompiler().errorVersion("1.0alpha1", tokenToASTObject(beginToken), 1229 "change to perthis or pertarget as appropriate"); 1230 eatTopToken(LPAREN); 1231 Pcd pointcut = parsePcd(); 1232 eatTopToken(RPAREN); 1233 return null; 1234 } else if (name.equals("eachcflow")) { 1235 getCompiler().warnVersion("1.0alpha1", tokenToASTObject(beginToken), 1236 "change 'of eachcflow' to 'percflow'"); 1237 eatTopToken(LPAREN); 1238 Pcd pointcut = parsePcd(); 1239 eatTopToken(RPAREN); 1240 ret = new PerCFlow(dummySource,pointcut, true); 1241 } else if (name.equals("eachcflowbelow")) { 1242 getCompiler().warnVersion("1.0alpha1", tokenToASTObject(beginToken), 1243 "change 'of eachcflowbelow' to 'percflowbelow'"); 1244 eatTopToken(LPAREN); 1245 Pcd pointcut = parsePcd(); 1246 eatTopToken(RPAREN); 1247 ret = new PerCFlow(dummySource,pointcut, false); 1248 } else if (name.equals("eachJVM")) { 1249 getCompiler().warnVersion("1.0alpha1", tokenToASTObject(beginToken), 1250 "change 'of eachJVM' to 'issingleton'"); 1251 eatTopToken(LPAREN); 1252 eatTopToken(RPAREN); 1253 ret = new PerSingleton(dummySource); 1254 } else { 1255 throwError(beginToken, 1256 "expected issingleton, pertarget, perthis, percflow or percflowbelow"); 1257 } 1258 1259 addContext(ret, beginToken); 1260 return ret; 1261 } 1262 1263 class PointcutDecParser extends DecParser { 1264 public Dec parse() { 1265 final int legalModifiers = Modifiers.PUBLIC | Modifiers.ABSTRACT | 1266 Modifiers.FINAL | Modifiers.STATIC | 1267 Modifiers.PRIVATE | Modifiers.PROTECTED; 1268 1269 Modifiers modifiers = parseModifiers(legalModifiers); 1270 eatKeyword("pointcut"); 1271 1272 String name = parseId(); 1273 Formals formals = parseFormals(); 1274 TypeD resultTypeD = parseOptionalReturnTypeD(); 1275 1276 if (modifiers.isAbstract()) { 1277 if (peekToken().kind == COLON) { 1278 throwError(null, "abstract pointcut can't have body"); 1279 } 1280 eatTopToken(SEMICOLON); 1281 return new PointcutDec(dummySource,modifiers, name, resultTypeD, formals, new EmptyPcd(dummySource)); 1282 } else { 1283 Pcd pointcut; 1284 1285 if (maybeEatToken(COLON)) { 1286 pointcut = parsePcd(); 1287 eatTopToken(SEMICOLON); 1288 } else { 1289 pointcut = new EmptyPcd(dummySource); 1290 } 1291 1292 return new PointcutDec(dummySource,modifiers, name, resultTypeD, formals, pointcut); 1293 } 1294 } 1295 } 1296 1297 1298 class AspectDecParser extends DecParser { 1299 public Dec parse() { 1300 throw new RuntimeException (); 1302 } 1303 public Dec parse(boolean isNotMethodLocal) { 1304 int legalModifiers; 1305 if (peekEnclosingTypeDec() == null) { 1306 legalModifiers = Modifiers.PUBLIC | Modifiers.ABSTRACT | Modifiers.FINAL | 1307 Modifiers.STRICT | Modifiers.PRIVILEGED; 1308 } else if (inInterface) { 1309 legalModifiers = Modifiers.PUBLIC | Modifiers.ABSTRACT | Modifiers.FINAL | 1310 Modifiers.STRICT | Modifiers.PRIVILEGED | Modifiers.STATIC; 1311 1312 } else { 1313 legalModifiers = Modifiers.PUBLIC | Modifiers.ABSTRACT | Modifiers.FINAL | 1314 Modifiers.STRICT | Modifiers.PRIVILEGED | 1315 Modifiers.PRIVATE | Modifiers.PROTECTED | Modifiers.STATIC; 1316 } 1317 1318 Modifiers modifiers = parseModifiers(legalModifiers); 1319 if (inInterface) modifiers.setPublic(true); 1320 1321 eatKeyword("aspect"); 1322 String id = parseId(); 1323 1324 TypeD superClass = null; 1325 if (maybeEatKeyword("extends")) { 1326 superClass = parseTypeD(); 1327 } 1328 TypeDs _implements = null; 1329 if (maybeEatKeyword("implements")) { 1330 _implements = parseTypeDs(); 1331 } 1332 GenTypeName _dominates = null; 1333 if (maybeEatKeyword("dominates")) { 1334 _dominates = parseGenTypeName(); 1335 } 1336 1337 PerClause perClause = null; 1339 if (maybeEatKeyword("of")) { 1340 perClause = parseOldOfClause(); 1342 } else { 1343 perClause = parsePerClause(); 1344 } 1345 1346 TypeDec ret = 1347 new AspectDec(dummySource, modifiers, id, superClass, _implements, 1348 _dominates, perClause, null); 1349 1350 ret.setEnclosingTypeDec(peekEnclosingTypeDec()); 1351 pushEnclosingTypeDec(ret); 1352 Decs body = null; 1353 boolean oldInInterface = inInterface; 1354 boolean oldParseInterfaceOnly = parseInterfaceOnly; 1355 try { 1356 inInterface = false; 1357 parseInterfaceOnly = false; 1358 body = parseDecs(aspectDecParsers); 1359 } finally { 1360 inInterface = oldInInterface; 1361 parseInterfaceOnly = oldParseInterfaceOnly; 1362 } 1363 popEnclosingTypeDec(); 1364 1365 ret.setBody(body); 1366 if (peekEnclosingTypeDec() == null) currentCompilationUnit.addDefinedType(ret); 1367 return ret; 1368 } 1369 } 1370 1371 class DeclareParser extends DecParser { 1372 public Dec parse() { 1373 parseNoModifiers(); 1374 eatKeyword("declare"); 1375 1376 String kind = parseId(); 1377 1378 if (kind.equals("parents")) { 1379 eatTopToken(COLON); 1380 1381 GenTypeName typeName = parseGenTypeName(); 1382 boolean isImplements; 1383 if (maybeEatKeyword("implements")) { 1384 isImplements = true; 1385 } else { 1386 eatKeyword("extends"); 1387 isImplements = false; 1388 } 1389 TypeDs typeDs = parseTypeDs(); 1390 Dec ret = new IntroducedSuperDec(dummySource, typeName, typeDs, isImplements); 1391 eatTopToken(SEMICOLON); 1392 return ret; 1393 } else if (kind.equals("error") || kind.equals("warning")) { 1394 boolean isWarning = kind.equals("warning"); 1395 eatTopToken(COLON); 1396 Pcd pointcut = parsePcd(); 1397 eatTopToken(COLON); 1398 Expr message = parseExpr(); 1399 return new ShowErrorDec(dummySource, pointcut, message, isWarning); 1400 } else if (kind.equals("soft")) { 1401 eatTopToken(COLON); 1402 GenTypeName typeName = parseGenTypeName(); 1403 eatTopToken(COLON); 1404 Pcd pointcut = parsePcd(); 1405 return new SoftThrowableDec(dummySource, typeName, pointcut); 1406 } else { 1407 throwError(peekToken(-1), "no declare " + kind + " is defined"); 1408 return null; 1409 } 1410 } 1411 } 1412 1413 class BeforeDecParser extends DecParser { 1414 public Dec parse() { 1415 Modifiers modifiers = parseModifiers(Modifiers.STATIC | Modifiers.STRICT); 1416 eatKeyword("before"); 1417 1418 Formals formals = parseFormals(); 1419 TypeDs _throws = parseThrows(); 1420 eatTopToken(COLON); 1422 1423 Pcd pointcut = parsePcd(); 1424 1425 return new BeforeAdviceDec(dummySource,modifiers, formals, _throws, pointcut, parseCodeBodyFully()); 1426 } 1427 } 1428 1429 public AroundAdviceDec parseAroundAdviceDec(Modifiers modifiers, TypeD resultTypeD) { 1431 1433 Formals formals = parseFormals(); 1434 TypeDs _throws = parseThrows(); 1435 eatTopToken(COLON); 1436 1437 Pcd pointcut = parsePcd(); 1438 1439 return new AroundAdviceDec(dummySource,modifiers, resultTypeD, formals, _throws, pointcut, parseCodeBodyFully()); 1440 } 1441 1442 class AroundDecParser extends DecParser { 1443 public Dec parse() { 1444 Modifiers modifiers = parseModifiers(Modifiers.STATIC | Modifiers.STRICT); 1445 1446 boolean needReturns = false; 1447 TypeD resultTypeD = null; 1448 if (maybeEatKeyword("around")) { 1449 needReturns = true; 1450 getCompiler().warnVersion("1.0alpha1", 1451 tokenToASTObject(peekToken(-1)), 1452 "the return type now goes before the around keyword,\n" + 1453 "i.e. Object around() instead of around() returns Object"); 1454 } else { 1455 resultTypeD = parseTypeD(); 1456 eatKeyword("around"); 1457 } 1458 1459 Formals formals = parseFormals(); 1460 1462 1463 if (needReturns) { 1464 if (!maybeEatKeyword("returns") ) { 1465 getCompiler().showError(formals, "return type required for around"); 1466 } else { 1467 resultTypeD = parseTypeD(); 1468 } 1469 } 1470 TypeDs _throws = parseThrows(); 1471 eatTopToken(COLON); 1472 1473 Pcd pointcut = parsePcd(); 1474 1475 return new AroundAdviceDec(dummySource,modifiers, resultTypeD, formals, _throws, pointcut, parseCodeBodyFully()); 1476 } 1477 } 1478 1479 class AfterDecParser extends DecParser { 1480 public Dec parse() { 1481 Modifiers modifiers = parseModifiers(Modifiers.STATIC | Modifiers.STRICT); 1482 eatKeyword("after"); 1483 1484 Formals formals = parseFormals(); 1485 1486 if (maybeEatKeyword("returning")) { 1487 FormalDec formal = null; 1488 if (maybeEatToken(LPAREN)) { 1489 if (peekToken().kind != RPAREN) { 1490 formal = parseFormal(); 1491 } 1492 eatTopToken(RPAREN); 1493 } 1494 1495 TypeDs _throws = parseThrows(); 1496 eatTopToken(COLON); 1497 1498 Pcd pointcut = parsePcd(); 1499 return new AfterReturningAdviceDec(dummySource,modifiers, formals, formal, _throws, pointcut, parseCodeBodyFully()); 1500 } else if (maybeEatKeyword("throwing")) { 1501 FormalDec formal = null; 1502 if (maybeEatToken(LPAREN)) { 1503 if (peekToken().kind != RPAREN) { 1504 formal = parseFormal(); 1505 } 1506 eatTopToken(RPAREN); 1507 } 1508 TypeDs _throws = parseThrows(); 1509 eatTopToken(COLON); 1510 Pcd pointcut = parsePcd(); 1511 return new AfterThrowingAdviceDec(dummySource,modifiers, formals, formal, _throws, pointcut, parseCodeBodyFully()); 1512 } else { 1513 TypeDs _throws = parseThrows(); 1514 eatTopToken(COLON); 1515 Pcd pointcut = parsePcd(); 1516 return new AfterAdviceDec(dummySource,modifiers, formals, _throws, pointcut, parseCodeBodyFully()); 1517 } 1518 } 1519 } 1520} 1521 | Popular Tags |