You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

PatternParser.java 44KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482
  1. /* *******************************************************************
  2. * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
  3. * 2005 Contributors
  4. * All rights reserved.
  5. * This program and the accompanying materials are made available
  6. * under the terms of the Eclipse Public License v1.0
  7. * which accompanies this distribution and is available at
  8. * http://www.eclipse.org/legal/epl-v10.html
  9. *
  10. * Contributors:
  11. * PARC initial implementation
  12. * Adrian Colyer many updates since....
  13. * ******************************************************************/
  14. package org.aspectj.weaver.patterns;
  15. import java.util.ArrayList;
  16. import java.util.Collections;
  17. import java.util.Iterator;
  18. import java.util.List;
  19. import java.util.Set;
  20. import org.aspectj.weaver.ISourceContext;
  21. import org.aspectj.weaver.Member;
  22. import org.aspectj.weaver.Shadow;
  23. import org.aspectj.weaver.UnresolvedType;
  24. import org.aspectj.weaver.internal.tools.PointcutDesignatorHandlerBasedPointcut;
  25. import org.aspectj.weaver.reflect.ReflectionWorld;
  26. import org.aspectj.weaver.tools.ContextBasedMatcher;
  27. import org.aspectj.weaver.tools.PointcutDesignatorHandler;
  28. //XXX doesn't handle errors for extra tokens very well (sometimes ignores)
  29. public class PatternParser {
  30. private ITokenSource tokenSource;
  31. private ISourceContext sourceContext;
  32. /** not thread-safe, but this class is not intended to be... */
  33. private boolean allowHasTypePatterns = false;
  34. /** extension handlers used in weaver tools API only */
  35. private Set pointcutDesignatorHandlers = Collections.EMPTY_SET;
  36. private ReflectionWorld world;
  37. /**
  38. * Constructor for PatternParser.
  39. */
  40. public PatternParser(ITokenSource tokenSource) {
  41. super();
  42. this.tokenSource = tokenSource;
  43. this.sourceContext = tokenSource.getSourceContext();
  44. }
  45. /** only used by weaver tools API */
  46. public void setPointcutDesignatorHandlers(Set handlers, ReflectionWorld world) {
  47. this.pointcutDesignatorHandlers = handlers;
  48. this.world = world;
  49. }
  50. public PerClause maybeParsePerClause() {
  51. IToken tok = tokenSource.peek();
  52. if (tok == IToken.EOF) return null;
  53. if (tok.isIdentifier()) {
  54. String name = tok.getString();
  55. if (name.equals("issingleton")) {
  56. return parsePerSingleton();
  57. } else if (name.equals("perthis")) {
  58. return parsePerObject(true);
  59. } else if (name.equals("pertarget")) {
  60. return parsePerObject(false);
  61. } else if (name.equals("percflow")) {
  62. return parsePerCflow(false);
  63. } else if (name.equals("percflowbelow")) {
  64. return parsePerCflow(true);
  65. } else if (name.equals("pertypewithin")) { // PTWIMPL Parse the pertypewithin clause
  66. return parsePerTypeWithin();
  67. } else {
  68. return null;
  69. }
  70. }
  71. return null;
  72. }
  73. private PerClause parsePerCflow(boolean isBelow) {
  74. parseIdentifier();
  75. eat("(");
  76. Pointcut entry = parsePointcut();
  77. eat(")");
  78. return new PerCflow(entry, isBelow);
  79. }
  80. private PerClause parsePerObject(boolean isThis) {
  81. parseIdentifier();
  82. eat("(");
  83. Pointcut entry = parsePointcut();
  84. eat(")");
  85. return new PerObject(entry, isThis);
  86. }
  87. private PerClause parsePerTypeWithin() {
  88. parseIdentifier();
  89. eat("(");
  90. TypePattern withinTypePattern = parseTypePattern();
  91. eat(")");
  92. return new PerTypeWithin(withinTypePattern);
  93. }
  94. private PerClause parsePerSingleton() {
  95. parseIdentifier();
  96. eat("(");
  97. eat(")");
  98. return new PerSingleton();
  99. }
  100. public Declare parseDeclare() {
  101. int startPos = tokenSource.peek().getStart();
  102. eatIdentifier("declare");
  103. String kind = parseIdentifier();
  104. Declare ret;
  105. if (kind.equals("error")) {
  106. eat(":");
  107. ret = parseErrorOrWarning(true);
  108. } else if (kind.equals("warning")) {
  109. eat(":");
  110. ret = parseErrorOrWarning(false);
  111. } else if (kind.equals("precedence")) {
  112. eat(":");
  113. ret = parseDominates();
  114. } else if (kind.equals("dominates")) {
  115. throw new ParserException("name changed to declare precedence", tokenSource.peek(-2));
  116. } else if (kind.equals("parents")) {
  117. ret = parseParents();
  118. } else if (kind.equals("soft")) {
  119. eat(":");
  120. ret = parseSoft();
  121. } else {
  122. throw new ParserException("expected one of error, warning, parents, soft, precedence, @type, @method, @constructor, @field",
  123. tokenSource.peek(-1));
  124. }
  125. int endPos = tokenSource.peek(-1).getEnd();
  126. ret.setLocation(sourceContext, startPos, endPos);
  127. return ret;
  128. }
  129. public Declare parseDeclareAnnotation() {
  130. int startPos = tokenSource.peek().getStart();
  131. eatIdentifier("declare");
  132. eat("@");
  133. String kind = parseIdentifier();
  134. eat(":");
  135. Declare ret;
  136. if (kind.equals("type")) {
  137. ret = parseDeclareAtType();
  138. } else if (kind.equals("method")) {
  139. ret = parseDeclareAtMethod(true);
  140. } else if (kind.equals("field")) {
  141. ret = parseDeclareAtField();
  142. } else if (kind.equals("constructor")) {
  143. ret = parseDeclareAtMethod(false);
  144. } else {
  145. throw new ParserException("one of type, method, field, constructor",tokenSource.peek(-1));
  146. }
  147. eat(";");
  148. int endPos = tokenSource.peek(-1).getEnd();
  149. ret.setLocation(sourceContext, startPos, endPos);
  150. return ret;
  151. }
  152. public DeclareAnnotation parseDeclareAtType() {
  153. allowHasTypePatterns = true;
  154. TypePattern p = parseTypePattern();
  155. allowHasTypePatterns = false;
  156. return new DeclareAnnotation(DeclareAnnotation.AT_TYPE,p);
  157. }
  158. public DeclareAnnotation parseDeclareAtMethod(boolean isMethod) {
  159. SignaturePattern sp = parseMethodOrConstructorSignaturePattern();
  160. boolean isConstructorPattern = (sp.getKind() == Member.CONSTRUCTOR);
  161. if (isMethod && isConstructorPattern) {
  162. throw new ParserException("method signature pattern",tokenSource.peek(-1));
  163. }
  164. if (!isMethod && !isConstructorPattern) {
  165. throw new ParserException("constructor signature pattern",tokenSource.peek(-1));
  166. }
  167. if (isConstructorPattern) return new DeclareAnnotation(DeclareAnnotation.AT_CONSTRUCTOR,sp);
  168. else return new DeclareAnnotation(DeclareAnnotation.AT_METHOD,sp);
  169. }
  170. public DeclareAnnotation parseDeclareAtField() {
  171. return new DeclareAnnotation(DeclareAnnotation.AT_FIELD,parseFieldSignaturePattern());
  172. }
  173. public DeclarePrecedence parseDominates() {
  174. List l = new ArrayList();
  175. do {
  176. l.add(parseTypePattern());
  177. } while (maybeEat(","));
  178. return new DeclarePrecedence(l);
  179. }
  180. private Declare parseParents() {
  181. /*
  182. * simplified design requires use of raw types for declare parents, no generic spec. allowed
  183. * String[] typeParameters = maybeParseSimpleTypeVariableList();
  184. */
  185. eat(":");
  186. allowHasTypePatterns = true;
  187. TypePattern p = parseTypePattern(false);
  188. allowHasTypePatterns = false;
  189. IToken t = tokenSource.next();
  190. if (!(t.getString().equals("extends") || t.getString().equals("implements"))) {
  191. throw new ParserException("extends or implements", t);
  192. }
  193. boolean isExtends = t.getString().equals("extends");
  194. List l = new ArrayList();
  195. do {
  196. l.add(parseTypePattern());
  197. } while (maybeEat(","));
  198. //XXX somewhere in the chain we need to enforce that we have only ExactTypePatterns
  199. DeclareParents decp = new DeclareParents(p, l,isExtends);
  200. return decp;
  201. }
  202. private Declare parseSoft() {
  203. TypePattern p = parseTypePattern();
  204. eat(":");
  205. Pointcut pointcut = parsePointcut();
  206. return new DeclareSoft(p, pointcut);
  207. }
  208. private Declare parseErrorOrWarning(boolean isError) {
  209. Pointcut pointcut = parsePointcut();
  210. eat(":");
  211. String message = parsePossibleStringSequence(true);
  212. return new DeclareErrorOrWarning(isError, pointcut, message);
  213. }
  214. public Pointcut parsePointcut() {
  215. Pointcut p = parseAtomicPointcut();
  216. if (maybeEat("&&")) {
  217. p = new AndPointcut(p, parseNotOrPointcut());
  218. }
  219. if (maybeEat("||")) {
  220. p = new OrPointcut(p, parsePointcut());
  221. }
  222. return p;
  223. }
  224. private Pointcut parseNotOrPointcut() {
  225. Pointcut p = parseAtomicPointcut();
  226. if (maybeEat("&&")) {
  227. p = new AndPointcut(p, parsePointcut());
  228. }
  229. return p;
  230. }
  231. private Pointcut parseAtomicPointcut() {
  232. if (maybeEat("!")) {
  233. int startPos = tokenSource.peek(-1).getStart();
  234. Pointcut p = new NotPointcut(parseAtomicPointcut(), startPos);
  235. return p;
  236. }
  237. if (maybeEat("(")) {
  238. Pointcut p = parsePointcut();
  239. eat(")");
  240. return p;
  241. }
  242. if (maybeEat("@")) {
  243. int startPos = tokenSource.peek().getStart();
  244. Pointcut p = parseAnnotationPointcut();
  245. int endPos = tokenSource.peek(-1).getEnd();
  246. p.setLocation(sourceContext, startPos, endPos);
  247. return p;
  248. }
  249. int startPos = tokenSource.peek().getStart();
  250. Pointcut p = parseSinglePointcut();
  251. int endPos = tokenSource.peek(-1).getEnd();
  252. p.setLocation(sourceContext, startPos, endPos);
  253. return p;
  254. }
  255. public Pointcut parseSinglePointcut() {
  256. int start = tokenSource.getIndex();
  257. IToken t = tokenSource.peek();
  258. Pointcut p = t.maybeGetParsedPointcut();
  259. if (p != null) {
  260. tokenSource.next();
  261. return p;
  262. }
  263. String kind = parseIdentifier();
  264. // IToken possibleTypeVariableToken = tokenSource.peek();
  265. // String[] typeVariables = maybeParseSimpleTypeVariableList();
  266. if (kind.equals("execution") || kind.equals("call") ||
  267. kind.equals("get") || kind.equals("set")) {
  268. p = parseKindedPointcut(kind);
  269. } else if (kind.equals("args")) {
  270. p = parseArgsPointcut();
  271. } else if (kind.equals("this")) {
  272. p = parseThisOrTargetPointcut(kind);
  273. } else if (kind.equals("target")) {
  274. p = parseThisOrTargetPointcut(kind);
  275. } else if (kind.equals("within")) {
  276. p = parseWithinPointcut();
  277. } else if (kind.equals("withincode")) {
  278. p = parseWithinCodePointcut();
  279. } else if (kind.equals("cflow")) {
  280. p = parseCflowPointcut(false);
  281. } else if (kind.equals("cflowbelow")) {
  282. p = parseCflowPointcut(true);
  283. } else if (kind.equals("adviceexecution")) {
  284. eat("(");
  285. eat(")");
  286. p = new KindedPointcut(Shadow.AdviceExecution,
  287. new SignaturePattern(Member.ADVICE, ModifiersPattern.ANY,
  288. TypePattern.ANY, TypePattern.ANY, NamePattern.ANY,
  289. TypePatternList.ANY,
  290. ThrowsPattern.ANY,
  291. AnnotationTypePattern.ANY));
  292. } else if (kind.equals("handler")) {
  293. eat("(");
  294. TypePattern typePat = parseTypePattern(false);
  295. eat(")");
  296. p = new HandlerPointcut(typePat);
  297. } else if (kind.equals("lock") || kind.equals("unlock")) {
  298. p = parseMonitorPointcut(kind);
  299. } else if (kind.equals("initialization")) {
  300. eat("(");
  301. SignaturePattern sig = parseConstructorSignaturePattern();
  302. eat(")");
  303. p = new KindedPointcut(Shadow.Initialization, sig);
  304. } else if (kind.equals("staticinitialization")) {
  305. eat("(");
  306. TypePattern typePat = parseTypePattern(false);
  307. eat(")");
  308. p = new KindedPointcut(Shadow.StaticInitialization,
  309. new SignaturePattern(Member.STATIC_INITIALIZATION, ModifiersPattern.ANY,
  310. TypePattern.ANY, typePat, NamePattern.ANY, TypePatternList.EMPTY,
  311. ThrowsPattern.ANY,AnnotationTypePattern.ANY));
  312. } else if (kind.equals("preinitialization")) {
  313. eat("(");
  314. SignaturePattern sig = parseConstructorSignaturePattern();
  315. eat(")");
  316. p = new KindedPointcut(Shadow.PreInitialization, sig);
  317. } else if (kind.equals("if")) {
  318. // @style support allows if(), if(true), if(false)
  319. eat("(");
  320. if (maybeEatIdentifier("true")) {
  321. eat(")");
  322. p = new IfPointcut.IfTruePointcut();
  323. } else if (maybeEatIdentifier("false")) {
  324. eat(")");
  325. p = new IfPointcut.IfFalsePointcut();
  326. } else {
  327. eat(")");
  328. // TODO - Alex has some token stuff going on here to get a readable name in place of ""...
  329. p = new IfPointcut("");
  330. }
  331. }
  332. else {
  333. boolean matchedByExtensionDesignator = false;
  334. // see if a registered handler wants to parse it, otherwise
  335. // treat as a reference pointcut
  336. for (Iterator iter = this.pointcutDesignatorHandlers.iterator(); iter.hasNext();) {
  337. PointcutDesignatorHandler pcd = (PointcutDesignatorHandler) iter.next();
  338. if (pcd.getDesignatorName().equals(kind)) {
  339. p = parseDesignatorPointcut(pcd);
  340. matchedByExtensionDesignator = true;
  341. }
  342. }
  343. if (!matchedByExtensionDesignator) {
  344. tokenSource.setIndex(start);
  345. p = parseReferencePointcut();
  346. }
  347. }
  348. return p;
  349. }
  350. private void assertNoTypeVariables(String[] tvs, String errorMessage,IToken token) {
  351. if ( tvs != null ) throw new ParserException(errorMessage,token);
  352. }
  353. public Pointcut parseAnnotationPointcut() {
  354. int start = tokenSource.getIndex();
  355. IToken t = tokenSource.peek();
  356. String kind = parseIdentifier();
  357. IToken possibleTypeVariableToken = tokenSource.peek();
  358. String[] typeVariables = maybeParseSimpleTypeVariableList();
  359. if (typeVariables != null) {
  360. String message = "(";
  361. assertNoTypeVariables(typeVariables, message, possibleTypeVariableToken);
  362. }
  363. tokenSource.setIndex(start);
  364. if (kind.equals("annotation")) {
  365. return parseAtAnnotationPointcut();
  366. } else if (kind.equals("args")) {
  367. return parseArgsAnnotationPointcut();
  368. } else if (kind.equals("this") || kind.equals("target")) {
  369. return parseThisOrTargetAnnotationPointcut();
  370. } else if (kind.equals("within")) {
  371. return parseWithinAnnotationPointcut();
  372. } else if (kind.equals("withincode")) {
  373. return parseWithinCodeAnnotationPointcut();
  374. } throw new ParserException("pointcut name", t);
  375. }
  376. private Pointcut parseAtAnnotationPointcut() {
  377. parseIdentifier();
  378. eat("(");
  379. if (maybeEat(")")) {
  380. throw new ParserException("@AnnotationName or parameter", tokenSource.peek());
  381. }
  382. ExactAnnotationTypePattern type = parseAnnotationNameOrVarTypePattern();
  383. eat(")");
  384. return new AnnotationPointcut(type);
  385. }
  386. private SignaturePattern parseConstructorSignaturePattern() {
  387. SignaturePattern ret = parseMethodOrConstructorSignaturePattern();
  388. if (ret.getKind() == Member.CONSTRUCTOR) return ret;
  389. throw new ParserException("constructor pattern required, found method pattern",
  390. ret);
  391. }
  392. private Pointcut parseWithinCodePointcut() {
  393. //parseIdentifier();
  394. eat("(");
  395. SignaturePattern sig = parseMethodOrConstructorSignaturePattern();
  396. eat(")");
  397. return new WithincodePointcut(sig);
  398. }
  399. private Pointcut parseCflowPointcut(boolean isBelow) {
  400. //parseIdentifier();
  401. eat("(");
  402. Pointcut entry = parsePointcut();
  403. eat(")");
  404. return new CflowPointcut(entry, isBelow, null);
  405. }
  406. /**
  407. * Method parseWithinPointcut.
  408. * @return Pointcut
  409. */
  410. private Pointcut parseWithinPointcut() {
  411. //parseIdentifier();
  412. eat("(");
  413. TypePattern type = parseTypePattern();
  414. eat(")");
  415. return new WithinPointcut(type);
  416. }
  417. /**
  418. * Method parseThisOrTargetPointcut.
  419. * @return Pointcut
  420. */
  421. private Pointcut parseThisOrTargetPointcut(String kind) {
  422. eat("(");
  423. TypePattern type = parseTypePattern();
  424. eat(")");
  425. return new ThisOrTargetPointcut(kind.equals("this"), type);
  426. }
  427. private Pointcut parseThisOrTargetAnnotationPointcut() {
  428. String kind = parseIdentifier();
  429. eat("(");
  430. if (maybeEat(")")) {
  431. throw new ParserException("expecting @AnnotationName or parameter, but found ')'", tokenSource.peek());
  432. }
  433. ExactAnnotationTypePattern type = parseAnnotationNameOrVarTypePattern();
  434. eat(")");
  435. return new ThisOrTargetAnnotationPointcut(kind.equals("this"),type);
  436. }
  437. private Pointcut parseWithinAnnotationPointcut() {
  438. String kind = parseIdentifier();
  439. eat("(");
  440. if (maybeEat(")")) {
  441. throw new ParserException("expecting @AnnotationName or parameter, but found ')'", tokenSource.peek());
  442. }
  443. AnnotationTypePattern type = parseAnnotationNameOrVarTypePattern();
  444. eat(")");
  445. return new WithinAnnotationPointcut(type);
  446. }
  447. private Pointcut parseWithinCodeAnnotationPointcut() {
  448. String kind = parseIdentifier();
  449. eat("(");
  450. if (maybeEat(")")) {
  451. throw new ParserException("expecting @AnnotationName or parameter, but found ')'", tokenSource.peek());
  452. }
  453. ExactAnnotationTypePattern type = parseAnnotationNameOrVarTypePattern();
  454. eat(")");
  455. return new WithinCodeAnnotationPointcut(type);
  456. }
  457. /**
  458. * Method parseArgsPointcut.
  459. * @return Pointcut
  460. */
  461. private Pointcut parseArgsPointcut() {
  462. //parseIdentifier();
  463. TypePatternList arguments = parseArgumentsPattern();
  464. return new ArgsPointcut(arguments);
  465. }
  466. private Pointcut parseArgsAnnotationPointcut() {
  467. parseIdentifier();
  468. AnnotationPatternList arguments = parseArgumentsAnnotationPattern();
  469. return new ArgsAnnotationPointcut(arguments);
  470. }
  471. private Pointcut parseReferencePointcut() {
  472. TypePattern onType = parseTypePattern();
  473. NamePattern name = null;
  474. if (onType.typeParameters.size() > 0) {
  475. eat(".");
  476. name = parseNamePattern();
  477. } else {
  478. name = tryToExtractName(onType);
  479. }
  480. if (name == null) {
  481. throw new ParserException("name pattern", tokenSource.peek());
  482. }
  483. if (onType.toString().equals("")) {
  484. onType = null;
  485. }
  486. String simpleName = name.maybeGetSimpleName();
  487. if (simpleName == null) {
  488. throw new ParserException("(",tokenSource.peek(-1));
  489. }
  490. TypePatternList arguments = parseArgumentsPattern();
  491. return new ReferencePointcut(onType, simpleName, arguments);
  492. }
  493. private Pointcut parseDesignatorPointcut(PointcutDesignatorHandler pcdHandler) {
  494. eat("(");
  495. int parenCount = 1;
  496. StringBuffer pointcutBody = new StringBuffer();
  497. while (parenCount > 0) {
  498. if (maybeEat("(")) {
  499. parenCount++;
  500. pointcutBody.append("(");
  501. } else if (maybeEat(")")) {
  502. parenCount--;
  503. if (parenCount > 0) {
  504. pointcutBody.append(")");
  505. }
  506. } else {
  507. pointcutBody.append(nextToken().getString());
  508. }
  509. }
  510. ContextBasedMatcher pcExpr = pcdHandler.parse(pointcutBody.toString());
  511. return new PointcutDesignatorHandlerBasedPointcut(pcExpr,world);
  512. }
  513. public List parseDottedIdentifier() {
  514. List ret = new ArrayList();
  515. ret.add(parseIdentifier());
  516. while (maybeEat(".")) {
  517. ret.add(parseIdentifier());
  518. }
  519. return ret;
  520. }
  521. private KindedPointcut parseKindedPointcut(String kind) {
  522. eat("(");
  523. SignaturePattern sig;
  524. Shadow.Kind shadowKind = null;
  525. if (kind.equals("execution")) {
  526. sig = parseMethodOrConstructorSignaturePattern(true);
  527. if (sig.getKind() == Member.METHOD) {
  528. shadowKind = Shadow.MethodExecution;
  529. } else if (sig.getKind() == Member.CONSTRUCTOR) {
  530. shadowKind = Shadow.ConstructorExecution;
  531. }
  532. } else if (kind.equals("call")) {
  533. sig = parseMethodOrConstructorSignaturePattern();
  534. if (sig.getKind() == Member.METHOD) {
  535. shadowKind = Shadow.MethodCall;
  536. } else if (sig.getKind() == Member.CONSTRUCTOR) {
  537. shadowKind = Shadow.ConstructorCall;
  538. }
  539. } else if (kind.equals("get")) {
  540. sig = parseFieldSignaturePattern();
  541. shadowKind = Shadow.FieldGet;
  542. } else if (kind.equals("set")) {
  543. sig = parseFieldSignaturePattern();
  544. shadowKind = Shadow.FieldSet;
  545. } else {
  546. throw new ParserException("bad kind: " + kind, tokenSource.peek());
  547. }
  548. eat(")");
  549. return new KindedPointcut(shadowKind, sig);
  550. }
  551. /** Covers the 'lock()' and 'unlock()' pointcuts */
  552. private KindedPointcut parseMonitorPointcut(String kind) {
  553. eat("(");
  554. TypePattern type = TypePattern.ANY;
  555. eat(")");
  556. if (kind.equals("lock")) {
  557. return new KindedPointcut(Shadow.SynchronizationLock,
  558. new SignaturePattern(Member.MONITORENTER, ModifiersPattern.ANY,
  559. TypePattern.ANY,
  560. TypePattern.ANY,
  561. // type,
  562. NamePattern.ANY,
  563. TypePatternList.ANY,
  564. ThrowsPattern.ANY,
  565. AnnotationTypePattern.ANY));
  566. } else {
  567. return new KindedPointcut(Shadow.SynchronizationUnlock,
  568. new SignaturePattern(Member.MONITORENTER, ModifiersPattern.ANY,
  569. TypePattern.ANY,
  570. TypePattern.ANY,
  571. // type,
  572. NamePattern.ANY,
  573. TypePatternList.ANY,
  574. ThrowsPattern.ANY,
  575. AnnotationTypePattern.ANY));
  576. }
  577. }
  578. public TypePattern parseTypePattern() {
  579. return parseTypePattern(false);
  580. }
  581. public TypePattern parseTypePattern(boolean insideTypeParameters) {
  582. TypePattern p = parseAtomicTypePattern(insideTypeParameters);
  583. if (maybeEat("&&")) {
  584. p = new AndTypePattern(p, parseNotOrTypePattern(insideTypeParameters));
  585. }
  586. if (maybeEat("||")) {
  587. p = new OrTypePattern(p, parseTypePattern(insideTypeParameters));
  588. }
  589. return p;
  590. }
  591. private TypePattern parseNotOrTypePattern(boolean insideTypeParameters) {
  592. TypePattern p = parseAtomicTypePattern(insideTypeParameters);
  593. if (maybeEat("&&")) {
  594. p = new AndTypePattern(p, parseTypePattern(insideTypeParameters));
  595. }
  596. return p;
  597. }
  598. private TypePattern parseAtomicTypePattern(boolean insideTypeParameters) {
  599. AnnotationTypePattern ap = maybeParseAnnotationPattern();
  600. if (maybeEat("!")) {
  601. //int startPos = tokenSource.peek(-1).getStart();
  602. //??? we lose source location for true start of !type
  603. TypePattern p = new NotTypePattern(parseAtomicTypePattern(insideTypeParameters));
  604. p = setAnnotationPatternForTypePattern(p,ap);
  605. return p;
  606. }
  607. if (maybeEat("(")) {
  608. TypePattern p = parseTypePattern(insideTypeParameters);
  609. p = setAnnotationPatternForTypePattern(p,ap);
  610. eat(")");
  611. boolean isVarArgs = maybeEat("...");
  612. if (isVarArgs) p.setIsVarArgs(isVarArgs);
  613. boolean isIncludeSubtypes = maybeEat("+");
  614. if (isIncludeSubtypes) p.includeSubtypes = true; // need the test because (A+) should not set subtypes to false!
  615. return p;
  616. }
  617. int startPos = tokenSource.peek().getStart();
  618. TypePattern p = parseSingleTypePattern(insideTypeParameters);
  619. int endPos = tokenSource.peek(-1).getEnd();
  620. p = setAnnotationPatternForTypePattern(p,ap);
  621. p.setLocation(sourceContext, startPos, endPos);
  622. return p;
  623. }
  624. private TypePattern setAnnotationPatternForTypePattern(TypePattern t, AnnotationTypePattern ap) {
  625. TypePattern ret = t;
  626. if (ap != AnnotationTypePattern.ANY) {
  627. if (t == TypePattern.ANY) {
  628. ret = new WildTypePattern(new NamePattern[] {NamePattern.ANY},false,0,false,null);
  629. }
  630. if (t.annotationPattern == AnnotationTypePattern.ANY) {
  631. ret.setAnnotationTypePattern(ap);
  632. } else {
  633. ret.setAnnotationTypePattern(new AndAnnotationTypePattern(ap,t.annotationPattern)); //???
  634. }
  635. }
  636. return ret;
  637. }
  638. public AnnotationTypePattern maybeParseAnnotationPattern() {
  639. AnnotationTypePattern ret = AnnotationTypePattern.ANY;
  640. AnnotationTypePattern nextPattern = null;
  641. while ((nextPattern = maybeParseSingleAnnotationPattern()) != null) {
  642. if (ret == AnnotationTypePattern.ANY) {
  643. ret = nextPattern;
  644. } else {
  645. ret = new AndAnnotationTypePattern(ret,nextPattern);
  646. }
  647. }
  648. return ret;
  649. }
  650. public AnnotationTypePattern maybeParseSingleAnnotationPattern() {
  651. AnnotationTypePattern ret = null;
  652. // LALR(2) - fix by making "!@" a single token
  653. int startIndex = tokenSource.getIndex();
  654. if (maybeEat("!")) {
  655. if (maybeEat("@")) {
  656. if (maybeEat("(")) {
  657. TypePattern p = parseTypePattern();
  658. ret = new NotAnnotationTypePattern(new WildAnnotationTypePattern(p));
  659. eat(")");
  660. return ret;
  661. } else {
  662. TypePattern p = parseSingleTypePattern();
  663. ret = new NotAnnotationTypePattern(new WildAnnotationTypePattern(p));
  664. return ret;
  665. }
  666. } else {
  667. tokenSource.setIndex(startIndex); // not for us!
  668. return ret;
  669. }
  670. }
  671. if (maybeEat("@")) {
  672. if (maybeEat("(")) {
  673. TypePattern p = parseTypePattern();
  674. ret = new WildAnnotationTypePattern(p);
  675. eat(")");
  676. return ret;
  677. } else {
  678. TypePattern p = parseSingleTypePattern();
  679. ret = new WildAnnotationTypePattern(p);
  680. return ret;
  681. }
  682. } else {
  683. tokenSource.setIndex(startIndex); // not for us!
  684. return ret;
  685. }
  686. }
  687. public TypePattern parseSingleTypePattern() {
  688. return parseSingleTypePattern(false);
  689. }
  690. public TypePattern parseSingleTypePattern(boolean insideTypeParameters) {
  691. if (insideTypeParameters && maybeEat("?")) return parseGenericsWildcardTypePattern();
  692. if (allowHasTypePatterns) {
  693. if (maybeEatIdentifier("hasmethod")) return parseHasMethodTypePattern();
  694. if (maybeEatIdentifier("hasfield")) return parseHasFieldTypePattern();
  695. }
  696. List names = parseDottedNamePattern();
  697. int dim = 0;
  698. while (maybeEat("[")) {
  699. eat("]");
  700. dim++;
  701. }
  702. TypePatternList typeParameters = maybeParseTypeParameterList();
  703. int endPos = tokenSource.peek(-1).getEnd();
  704. boolean isVarArgs = maybeEat("...");
  705. boolean includeSubtypes = maybeEat("+");
  706. //??? what about the source location of any's????
  707. if (names.size() == 1 && ((NamePattern)names.get(0)).isAny() &&
  708. dim == 0 && !isVarArgs && typeParameters == null ) return TypePattern.ANY;
  709. // Notice we increase the dimensions if varargs is set. this is to allow type matching to
  710. // succeed later: The actual signature at runtime of a method declared varargs is an array type of
  711. // the original declared type (so Integer... becomes Integer[] in the bytecode). So, here for the
  712. // pattern 'Integer...' we create a WildTypePattern 'Integer[]' with varargs set. If this matches
  713. // during shadow matching, we confirm that the varargs flags match up before calling it a successful
  714. // match.
  715. return new WildTypePattern(names, includeSubtypes, dim+(isVarArgs?1:0), endPos,isVarArgs,typeParameters);
  716. }
  717. public TypePattern parseHasMethodTypePattern() {
  718. int startPos = tokenSource.peek(-1).getStart();
  719. eat("(");
  720. SignaturePattern sp = parseMethodOrConstructorSignaturePattern();
  721. eat(")");
  722. int endPos = tokenSource.peek(-1).getEnd();
  723. HasMemberTypePattern ret = new HasMemberTypePattern(sp);
  724. ret.setLocation(sourceContext, startPos, endPos);
  725. return ret;
  726. }
  727. public TypePattern parseHasFieldTypePattern() {
  728. int startPos = tokenSource.peek(-1).getStart();
  729. eat("(");
  730. SignaturePattern sp = parseFieldSignaturePattern();
  731. eat(")");
  732. int endPos = tokenSource.peek(-1).getEnd();
  733. HasMemberTypePattern ret = new HasMemberTypePattern(sp);
  734. ret.setLocation(sourceContext, startPos, endPos);
  735. return ret;
  736. }
  737. public TypePattern parseGenericsWildcardTypePattern() {
  738. List names = new ArrayList();
  739. names.add(new NamePattern("?"));
  740. TypePattern upperBound = null;
  741. TypePattern[] additionalInterfaceBounds = new TypePattern[0];
  742. TypePattern lowerBound = null;
  743. if (maybeEatIdentifier("extends")) {
  744. upperBound = parseTypePattern(false);
  745. additionalInterfaceBounds = maybeParseAdditionalInterfaceBounds();
  746. }
  747. if (maybeEatIdentifier("super")) {
  748. lowerBound = parseTypePattern(false);
  749. }
  750. int endPos = tokenSource.peek(-1).getEnd();
  751. return new WildTypePattern(names,false,0,endPos,false,null,upperBound,additionalInterfaceBounds,lowerBound);
  752. }
  753. // private AnnotationTypePattern completeAnnotationPattern(AnnotationTypePattern p) {
  754. // if (maybeEat("&&")) {
  755. // return new AndAnnotationTypePattern(p,parseNotOrAnnotationPattern());
  756. // }
  757. // if (maybeEat("||")) {
  758. // return new OrAnnotationTypePattern(p,parseAnnotationTypePattern());
  759. // }
  760. // return p;
  761. // }
  762. //
  763. // protected AnnotationTypePattern parseAnnotationTypePattern() {
  764. // AnnotationTypePattern ap = parseAtomicAnnotationPattern();
  765. // if (maybeEat("&&")) {
  766. // ap = new AndAnnotationTypePattern(ap, parseNotOrAnnotationPattern());
  767. // }
  768. //
  769. // if (maybeEat("||")) {
  770. // ap = new OrAnnotationTypePattern(ap, parseAnnotationTypePattern());
  771. // }
  772. // return ap;
  773. // }
  774. //
  775. // private AnnotationTypePattern parseNotOrAnnotationPattern() {
  776. // AnnotationTypePattern p = parseAtomicAnnotationPattern();
  777. // if (maybeEat("&&")) {
  778. // p = new AndAnnotationTypePattern(p,parseAnnotationTypePattern());
  779. // }
  780. // return p;
  781. // }
  782. protected ExactAnnotationTypePattern parseAnnotationNameOrVarTypePattern() {
  783. ExactAnnotationTypePattern p = null;
  784. int startPos = tokenSource.peek().getStart();
  785. if (maybeEat("@")) {
  786. throw new ParserException("@Foo form was deprecated in AspectJ 5 M2: annotation name or var ",tokenSource.peek(-1));
  787. }
  788. p = parseSimpleAnnotationName();
  789. int endPos = tokenSource.peek(-1).getEnd();
  790. p.setLocation(sourceContext,startPos,endPos);
  791. return p;
  792. }
  793. /**
  794. * @return
  795. */
  796. private ExactAnnotationTypePattern parseSimpleAnnotationName() {
  797. // the @ has already been eaten...
  798. ExactAnnotationTypePattern p;
  799. StringBuffer annotationName = new StringBuffer();
  800. annotationName.append(parseIdentifier());
  801. while (maybeEat(".")) {
  802. annotationName.append('.');
  803. annotationName.append(parseIdentifier());
  804. }
  805. UnresolvedType type = UnresolvedType.forName(annotationName.toString());
  806. p = new ExactAnnotationTypePattern(type);
  807. return p;
  808. }
  809. // private AnnotationTypePattern parseAtomicAnnotationPattern() {
  810. // if (maybeEat("!")) {
  811. // //int startPos = tokenSource.peek(-1).getStart();
  812. // //??? we lose source location for true start of !type
  813. // AnnotationTypePattern p = new NotAnnotationTypePattern(parseAtomicAnnotationPattern());
  814. // return p;
  815. // }
  816. // if (maybeEat("(")) {
  817. // AnnotationTypePattern p = parseAnnotationTypePattern();
  818. // eat(")");
  819. // return p;
  820. // }
  821. // int startPos = tokenSource.peek().getStart();
  822. // eat("@");
  823. // StringBuffer annotationName = new StringBuffer();
  824. // annotationName.append(parseIdentifier());
  825. // while (maybeEat(".")) {
  826. // annotationName.append('.');
  827. // annotationName.append(parseIdentifier());
  828. // }
  829. // UnresolvedType type = UnresolvedType.forName(annotationName.toString());
  830. // AnnotationTypePattern p = new ExactAnnotationTypePattern(type);
  831. // int endPos = tokenSource.peek(-1).getEnd();
  832. // p.setLocation(sourceContext, startPos, endPos);
  833. // return p;
  834. // }
  835. private boolean isAnnotationPattern(PatternNode p) {
  836. return (p instanceof AnnotationTypePattern);
  837. }
  838. public List parseDottedNamePattern() {
  839. List names = new ArrayList();
  840. StringBuffer buf = new StringBuffer();
  841. IToken previous = null;
  842. boolean justProcessedEllipsis = false; // Remember if we just dealt with an ellipsis (PR61536)
  843. boolean justProcessedDot = false;
  844. boolean onADot = false;
  845. while (true) {
  846. IToken tok = null;
  847. int startPos = tokenSource.peek().getStart();
  848. String afterDot = null;
  849. while (true) {
  850. if (previous !=null && previous.getString().equals(".")) justProcessedDot = true;
  851. tok = tokenSource.peek();
  852. onADot = (tok.getString().equals("."));
  853. if (previous != null) {
  854. if (!isAdjacent(previous, tok)) break;
  855. }
  856. if (tok.getString() == "*" || (tok.isIdentifier() && tok.getString()!="...")) {
  857. buf.append(tok.getString());
  858. } else if (tok.getString()=="...") {
  859. break;
  860. } else if (tok.getLiteralKind() != null) {
  861. //System.err.println("literal kind: " + tok.getString());
  862. String s = tok.getString();
  863. int dot = s.indexOf('.');
  864. if (dot != -1) {
  865. buf.append(s.substring(0, dot));
  866. afterDot = s.substring(dot+1);
  867. previous = tokenSource.next();
  868. break;
  869. }
  870. buf.append(s); // ??? so-so
  871. } else {
  872. break;
  873. }
  874. previous = tokenSource.next();
  875. //XXX need to handle floats and other fun stuff
  876. }
  877. int endPos = tokenSource.peek(-1).getEnd();
  878. if (buf.length() == 0 && names.isEmpty()) {
  879. throw new ParserException("name pattern", tok);
  880. }
  881. if (buf.length() == 0 && justProcessedEllipsis) {
  882. throw new ParserException("name pattern cannot finish with ..", tok);
  883. }
  884. if (buf.length() == 0 && justProcessedDot && !onADot) {
  885. throw new ParserException("name pattern cannot finish with .", tok);
  886. }
  887. if (buf.length() == 0) {
  888. names.add(NamePattern.ELLIPSIS);
  889. justProcessedEllipsis = true;
  890. } else {
  891. checkLegalName(buf.toString(), previous);
  892. NamePattern ret = new NamePattern(buf.toString());
  893. ret.setLocation(sourceContext, startPos, endPos);
  894. names.add(ret);
  895. justProcessedEllipsis = false;
  896. }
  897. if (afterDot == null) {
  898. buf.setLength(0);
  899. // no elipsis or dotted name part
  900. if (!maybeEat(".")) break;
  901. // go on
  902. else previous = tokenSource.peek(-1);
  903. } else {
  904. buf.setLength(0);
  905. buf.append(afterDot);
  906. afterDot = null;
  907. }
  908. }
  909. //System.err.println("parsed: " + names);
  910. return names;
  911. }
  912. public NamePattern parseNamePattern() {
  913. StringBuffer buf = new StringBuffer();
  914. IToken previous = null;
  915. IToken tok;
  916. int startPos = tokenSource.peek().getStart();
  917. while (true) {
  918. tok = tokenSource.peek();
  919. if (previous != null) {
  920. if (!isAdjacent(previous, tok)) break;
  921. }
  922. if (tok.getString() == "*" || tok.isIdentifier()) {
  923. buf.append(tok.getString());
  924. } else if (tok.getLiteralKind() != null) {
  925. //System.err.println("literal kind: " + tok.getString());
  926. String s = tok.getString();
  927. if (s.indexOf('.') != -1) break;
  928. buf.append(s); // ??? so-so
  929. } else {
  930. break;
  931. }
  932. previous = tokenSource.next();
  933. //XXX need to handle floats and other fun stuff
  934. }
  935. int endPos = tokenSource.peek(-1).getEnd();
  936. if (buf.length() == 0) {
  937. throw new ParserException("name pattern", tok);
  938. }
  939. checkLegalName(buf.toString(), previous);
  940. NamePattern ret = new NamePattern(buf.toString());
  941. ret.setLocation(sourceContext, startPos, endPos);
  942. return ret;
  943. }
  944. private void checkLegalName(String s, IToken tok) {
  945. char ch = s.charAt(0);
  946. if (!(ch == '*' || Character.isJavaIdentifierStart(ch))) {
  947. throw new ParserException("illegal identifier start (" + ch + ")", tok);
  948. }
  949. for (int i=1, len=s.length(); i < len; i++) {
  950. ch = s.charAt(i);
  951. if (!(ch == '*' || Character.isJavaIdentifierPart(ch))) {
  952. throw new ParserException("illegal identifier character (" + ch + ")", tok);
  953. }
  954. }
  955. }
  956. private boolean isAdjacent(IToken first, IToken second) {
  957. return first.getEnd() == second.getStart()-1;
  958. }
  959. public ModifiersPattern parseModifiersPattern() {
  960. return parseModifiersPattern(false);
  961. }
  962. public ModifiersPattern parseModifiersPattern(boolean allowTrivial) {
  963. int requiredFlags = 0;
  964. int forbiddenFlags = 0;
  965. int start;
  966. while (true) {
  967. start = tokenSource.getIndex();
  968. boolean isForbidden = false;
  969. isForbidden = maybeEat("!");
  970. IToken t = tokenSource.next();
  971. int flag = ModifiersPattern.getModifierFlag(t.getString(),allowTrivial);
  972. // working out the flag...
  973. if (flag==-2) {
  974. throw new ParserException("any modifier except 'trivial'",t);//tokenSource.peek(-1));
  975. }
  976. if (flag == -1) break;
  977. if (isForbidden) forbiddenFlags |= flag;
  978. else requiredFlags |= flag;
  979. }
  980. tokenSource.setIndex(start);
  981. if (requiredFlags == 0 && forbiddenFlags == 0) {
  982. return ModifiersPattern.ANY;
  983. } else {
  984. return new ModifiersPattern(requiredFlags, forbiddenFlags);
  985. }
  986. }
  987. public TypePatternList parseArgumentsPattern() {
  988. List patterns = new ArrayList();
  989. eat("(");
  990. if (maybeEat(")")) {
  991. return new TypePatternList();
  992. }
  993. do {
  994. if (maybeEat(".")) {
  995. eat(".");
  996. patterns.add(TypePattern.ELLIPSIS);
  997. } else {
  998. patterns.add(parseTypePattern());
  999. }
  1000. } while (maybeEat(","));
  1001. eat(")");
  1002. return new TypePatternList(patterns);
  1003. }
  1004. public AnnotationPatternList parseArgumentsAnnotationPattern() {
  1005. List patterns = new ArrayList();
  1006. eat("(");
  1007. if (maybeEat(")")) {
  1008. return new AnnotationPatternList();
  1009. }
  1010. do {
  1011. if (maybeEat(".")) {
  1012. eat(".");
  1013. patterns.add(AnnotationTypePattern.ELLIPSIS);
  1014. } else if (maybeEat("*")) {
  1015. patterns.add(AnnotationTypePattern.ANY);
  1016. } else {
  1017. patterns.add(parseAnnotationNameOrVarTypePattern());
  1018. }
  1019. } while (maybeEat(","));
  1020. eat(")");
  1021. return new AnnotationPatternList(patterns);
  1022. }
  1023. public ThrowsPattern parseOptionalThrowsPattern() {
  1024. IToken t = tokenSource.peek();
  1025. if (t.isIdentifier() && t.getString().equals("throws")) {
  1026. tokenSource.next();
  1027. List required = new ArrayList();
  1028. List forbidden = new ArrayList();
  1029. do {
  1030. boolean isForbidden = maybeEat("!");
  1031. //???might want an error for a second ! without a paren
  1032. TypePattern p = parseTypePattern();
  1033. if (isForbidden) forbidden.add(p);
  1034. else required.add(p);
  1035. } while (maybeEat(","));
  1036. return new ThrowsPattern(new TypePatternList(required), new TypePatternList(forbidden));
  1037. }
  1038. return ThrowsPattern.ANY;
  1039. }
  1040. public SignaturePattern parseMethodOrConstructorSignaturePattern() {
  1041. return parseMethodOrConstructorSignaturePattern(false);
  1042. }
  1043. public SignaturePattern parseMethodOrConstructorSignaturePattern(boolean allowTrivial) {
  1044. int startPos = tokenSource.peek().getStart();
  1045. AnnotationTypePattern annotationPattern = maybeParseAnnotationPattern();
  1046. ModifiersPattern modifiers = parseModifiersPattern(allowTrivial);
  1047. TypePattern returnType = parseTypePattern(false);
  1048. TypePattern declaringType;
  1049. NamePattern name = null;
  1050. Member.Kind kind;
  1051. // here we can check for 'new'
  1052. if (maybeEatNew(returnType)) {
  1053. kind = Member.CONSTRUCTOR;
  1054. if (returnType.toString().length() == 0) {
  1055. declaringType = TypePattern.ANY;
  1056. } else {
  1057. declaringType = returnType;
  1058. }
  1059. returnType = TypePattern.ANY;
  1060. name = NamePattern.ANY;
  1061. } else {
  1062. kind = Member.METHOD;
  1063. IToken nameToken = tokenSource.peek();
  1064. declaringType = parseTypePattern(false);
  1065. if (maybeEat(".")) {
  1066. nameToken = tokenSource.peek();
  1067. name = parseNamePattern();
  1068. } else {
  1069. name = tryToExtractName(declaringType);
  1070. if (declaringType.toString().equals("")) {
  1071. declaringType = TypePattern.ANY;
  1072. }
  1073. }
  1074. if (name == null) {
  1075. throw new ParserException("name pattern", tokenSource.peek());
  1076. }
  1077. String simpleName = name.maybeGetSimpleName();
  1078. //XXX should add check for any Java keywords
  1079. if (simpleName != null && simpleName.equals("new")) {
  1080. throw new ParserException("method name (not constructor)",
  1081. nameToken);
  1082. }
  1083. }
  1084. TypePatternList parameterTypes = parseArgumentsPattern();
  1085. ThrowsPattern throwsPattern = parseOptionalThrowsPattern();
  1086. SignaturePattern ret = new SignaturePattern(kind, modifiers, returnType, declaringType, name, parameterTypes, throwsPattern, annotationPattern);
  1087. int endPos = tokenSource.peek(-1).getEnd();
  1088. ret.setLocation(sourceContext, startPos, endPos);
  1089. return ret;
  1090. }
  1091. private boolean maybeEatNew(TypePattern returnType) {
  1092. if (returnType instanceof WildTypePattern) {
  1093. WildTypePattern p = (WildTypePattern)returnType;
  1094. if (p.maybeExtractName("new")) return true;
  1095. }
  1096. int start = tokenSource.getIndex();
  1097. if (maybeEat(".")) {
  1098. String id = maybeEatIdentifier();
  1099. if (id != null && id.equals("new")) return true;
  1100. tokenSource.setIndex(start);
  1101. }
  1102. return false;
  1103. }
  1104. public SignaturePattern parseFieldSignaturePattern() {
  1105. int startPos = tokenSource.peek().getStart();
  1106. // TypePatternList followMe = TypePatternList.ANY;
  1107. AnnotationTypePattern annotationPattern = maybeParseAnnotationPattern();
  1108. ModifiersPattern modifiers = parseModifiersPattern();
  1109. TypePattern returnType = parseTypePattern();
  1110. TypePattern declaringType = parseTypePattern();
  1111. NamePattern name;
  1112. //System.err.println("parsed field: " + declaringType.toString());
  1113. if (maybeEat(".")) {
  1114. name = parseNamePattern();
  1115. } else {
  1116. name = tryToExtractName(declaringType);
  1117. if (name == null) throw new ParserException("name pattern",tokenSource.peek());
  1118. if (declaringType.toString().equals("")) {
  1119. declaringType = TypePattern.ANY;
  1120. }
  1121. }
  1122. SignaturePattern ret = new SignaturePattern(Member.FIELD, modifiers, returnType,
  1123. declaringType, name, TypePatternList.ANY, ThrowsPattern.ANY,annotationPattern);
  1124. int endPos = tokenSource.peek(-1).getEnd();
  1125. ret.setLocation(sourceContext, startPos, endPos);
  1126. return ret;
  1127. }
  1128. private NamePattern tryToExtractName(TypePattern nextType) {
  1129. if (nextType == TypePattern.ANY) {
  1130. return NamePattern.ANY;
  1131. } else if (nextType instanceof WildTypePattern) {
  1132. WildTypePattern p = (WildTypePattern)nextType;
  1133. return p.extractName();
  1134. } else {
  1135. return null;
  1136. }
  1137. }
  1138. /**
  1139. * Parse type variable declarations for a generic method or at the start of a signature pointcut to identify
  1140. * type variable names in a generic type.
  1141. * @param includeParameterizedTypes
  1142. * @return
  1143. */
  1144. public TypeVariablePatternList maybeParseTypeVariableList() {
  1145. if (!maybeEat("<")) return null;
  1146. List typeVars = new ArrayList();
  1147. TypeVariablePattern t = parseTypeVariable();
  1148. typeVars.add(t);
  1149. while (maybeEat(",")) {
  1150. TypeVariablePattern nextT = parseTypeVariable();
  1151. typeVars.add(nextT);
  1152. }
  1153. eat(">");
  1154. TypeVariablePattern[] tvs = new TypeVariablePattern[typeVars.size()];
  1155. typeVars.toArray(tvs);
  1156. return new TypeVariablePatternList(tvs);
  1157. }
  1158. // of the form execution<T,S,V> - allows identifiers only
  1159. public String[] maybeParseSimpleTypeVariableList() {
  1160. if (!maybeEat("<")) return null;
  1161. List typeVarNames = new ArrayList();
  1162. do {
  1163. typeVarNames.add(parseIdentifier());
  1164. } while (maybeEat(","));
  1165. eat(">","',' or '>'");
  1166. String[] tvs = new String[typeVarNames.size()];
  1167. typeVarNames.toArray(tvs);
  1168. return tvs;
  1169. }
  1170. public TypePatternList maybeParseTypeParameterList() {
  1171. if (!maybeEat("<")) return null;
  1172. List typePats = new ArrayList();
  1173. do {
  1174. TypePattern tp = parseTypePattern(true);
  1175. typePats.add(tp);
  1176. } while(maybeEat(","));
  1177. eat(">");
  1178. TypePattern[] tps = new TypePattern[typePats.size()];
  1179. typePats.toArray(tps);
  1180. return new TypePatternList(tps);
  1181. }
  1182. public TypeVariablePattern parseTypeVariable() {
  1183. TypePattern upperBound = null;
  1184. TypePattern[] additionalInterfaceBounds = null;
  1185. TypePattern lowerBound = null;
  1186. String typeVariableName = null;
  1187. if (typeVariableName == null) typeVariableName = parseIdentifier();
  1188. if (maybeEatIdentifier("extends")) {
  1189. upperBound = parseTypePattern();
  1190. additionalInterfaceBounds = maybeParseAdditionalInterfaceBounds();
  1191. } else if (maybeEatIdentifier("super")) {
  1192. lowerBound = parseTypePattern();
  1193. }
  1194. return new TypeVariablePattern(typeVariableName,upperBound,additionalInterfaceBounds,lowerBound);
  1195. }
  1196. private TypePattern[] maybeParseAdditionalInterfaceBounds() {
  1197. List boundsList = new ArrayList();
  1198. while (maybeEat("&")) {
  1199. TypePattern tp = parseTypePattern();
  1200. boundsList.add(tp);
  1201. }
  1202. if (boundsList.size() == 0) return null;
  1203. TypePattern[] ret = new TypePattern[boundsList.size()];
  1204. boundsList.toArray(ret);
  1205. return ret;
  1206. }
  1207. public String parsePossibleStringSequence(boolean shouldEnd) {
  1208. StringBuffer result = new StringBuffer();
  1209. IToken token = tokenSource.next();
  1210. if (token.getLiteralKind()==null) {
  1211. throw new ParserException("string",token);
  1212. }
  1213. while (token.getLiteralKind().equals("string")) {
  1214. result.append(token.getString());
  1215. boolean plus = maybeEat("+");
  1216. if (!plus) break;
  1217. token = tokenSource.next();
  1218. if (token.getLiteralKind()==null) {
  1219. throw new ParserException("string",token);
  1220. }
  1221. }
  1222. eatIdentifier(";");
  1223. IToken t = tokenSource.next();
  1224. if (shouldEnd && t!=IToken.EOF) {
  1225. throw new ParserException("<string>;",token);
  1226. }
  1227. // bug 125027: since we've eaten the ";" we need to set the index
  1228. // to be one less otherwise the end position isn't set correctly.
  1229. int currentIndex = tokenSource.getIndex();
  1230. tokenSource.setIndex(currentIndex-1);
  1231. return result.toString();
  1232. }
  1233. public String parseStringLiteral() {
  1234. IToken token = tokenSource.next();
  1235. String literalKind = token.getLiteralKind();
  1236. if (literalKind == "string") {
  1237. return token.getString();
  1238. }
  1239. throw new ParserException("string", token);
  1240. }
  1241. public String parseIdentifier() {
  1242. IToken token = tokenSource.next();
  1243. if (token.isIdentifier()) return token.getString();
  1244. throw new ParserException("identifier", token);
  1245. }
  1246. public void eatIdentifier(String expectedValue) {
  1247. IToken next = tokenSource.next();
  1248. if (!next.getString().equals(expectedValue)) {
  1249. throw new ParserException(expectedValue, next);
  1250. }
  1251. }
  1252. public boolean maybeEatIdentifier(String expectedValue) {
  1253. IToken next = tokenSource.peek();
  1254. if (next.getString().equals(expectedValue)) {
  1255. tokenSource.next();
  1256. return true;
  1257. } else {
  1258. return false;
  1259. }
  1260. }
  1261. public void eat(String expectedValue) {
  1262. eat(expectedValue,expectedValue);
  1263. }
  1264. private void eat(String expectedValue,String expectedMessage) {
  1265. IToken next = nextToken();
  1266. if (next.getString() != expectedValue) {
  1267. if (expectedValue.equals(">") && next.getString().startsWith(">")) {
  1268. // handle problem of >> and >>> being lexed as single tokens
  1269. pendingRightArrows = BasicToken.makeLiteral(next.getString().substring(1).intern(), "string", next.getStart()+1, next.getEnd());
  1270. return;
  1271. }
  1272. throw new ParserException(expectedMessage, next);
  1273. }
  1274. }
  1275. private IToken pendingRightArrows;
  1276. private IToken nextToken() {
  1277. if (pendingRightArrows != null) {
  1278. IToken ret = pendingRightArrows;
  1279. pendingRightArrows = null;
  1280. return ret;
  1281. } else {
  1282. return tokenSource.next();
  1283. }
  1284. }
  1285. public boolean maybeEat(String token) {
  1286. IToken next = tokenSource.peek();
  1287. if (next.getString() == token) {
  1288. tokenSource.next();
  1289. return true;
  1290. } else {
  1291. return false;
  1292. }
  1293. }
  1294. public String maybeEatIdentifier() {
  1295. IToken next = tokenSource.peek();
  1296. if (next.isIdentifier()) {
  1297. tokenSource.next();
  1298. return next.getString();
  1299. } else {
  1300. return null;
  1301. }
  1302. }
  1303. public boolean peek(String token) {
  1304. IToken next = tokenSource.peek();
  1305. return next.getString() == token;
  1306. }
  1307. public void checkEof() {
  1308. IToken last = tokenSource.next();
  1309. if (last != IToken.EOF) {
  1310. throw new ParserException("unexpected pointcut element", last);
  1311. }
  1312. }
  1313. public PatternParser(String data) {
  1314. this(BasicTokenSource.makeTokenSource(data,null));
  1315. }
  1316. public PatternParser(String data, ISourceContext context) {
  1317. this(BasicTokenSource.makeTokenSource(data,context));
  1318. }
  1319. }