Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

PatternParser.java 59KB

15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
13 år sedan
13 år sedan
13 år sedan
15 år sedan
14 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
14 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
14 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
13 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
14 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
12 år sedan
14 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
12 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
14 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
14 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
14 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
12 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
13 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
14 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
14 år sedan
15 år sedan
15 år sedan
15 år sedan
14 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
14 år sedan
15 år sedan
15 år sedan
14 år sedan
15 år sedan
15 år sedan
15 år sedan
14 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
14 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
15 år sedan
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900
  1. /* *******************************************************************
  2. * Copyright (c) 2002,2010
  3. * All rights reserved.
  4. * This program and the accompanying materials are made available
  5. * under the terms of the Eclipse Public License v1.0
  6. * which accompanies this distribution and is available at
  7. * http://www.eclipse.org/legal/epl-v10.html
  8. *
  9. * Contributors:
  10. * PARC initial implementation
  11. * Adrian Colyer, IBM
  12. * Andy Clement, IBM, SpringSource
  13. * ******************************************************************/
  14. package org.aspectj.weaver.patterns;
  15. import java.util.ArrayList;
  16. import java.util.Collections;
  17. import java.util.HashMap;
  18. import java.util.List;
  19. import java.util.Map;
  20. import java.util.Set;
  21. import org.aspectj.weaver.ISourceContext;
  22. import org.aspectj.weaver.Member;
  23. import org.aspectj.weaver.MemberKind;
  24. import org.aspectj.weaver.Shadow;
  25. import org.aspectj.weaver.UnresolvedType;
  26. import org.aspectj.weaver.World;
  27. import org.aspectj.weaver.internal.tools.PointcutDesignatorHandlerBasedPointcut;
  28. import org.aspectj.weaver.tools.ContextBasedMatcher;
  29. import org.aspectj.weaver.tools.PointcutDesignatorHandler;
  30. /**
  31. * @author PARC
  32. * @author Adrian Colyer
  33. * @author Andy Clement
  34. */
  35. // XXX doesn't handle errors for extra tokens very well (sometimes ignores)
  36. public class PatternParser {
  37. private ITokenSource tokenSource;
  38. private ISourceContext sourceContext;
  39. /** not thread-safe, but this class is not intended to be... */
  40. private boolean allowHasTypePatterns = false;
  41. /** extension handlers used in weaver tools API only */
  42. private Set<PointcutDesignatorHandler> pointcutDesignatorHandlers = Collections.emptySet();
  43. private World world;
  44. /**
  45. * Constructor for PatternParser.
  46. */
  47. public PatternParser(ITokenSource tokenSource) {
  48. super();
  49. this.tokenSource = tokenSource;
  50. this.sourceContext = tokenSource.getSourceContext();
  51. }
  52. /** only used by weaver tools API */
  53. public void setPointcutDesignatorHandlers(Set<PointcutDesignatorHandler> handlers, World world) {
  54. this.pointcutDesignatorHandlers = handlers;
  55. this.world = world;
  56. }
  57. public PerClause maybeParsePerClause() {
  58. IToken tok = tokenSource.peek();
  59. if (tok == IToken.EOF) {
  60. return null;
  61. }
  62. if (tok.isIdentifier()) {
  63. String name = tok.getString();
  64. if (name.equals("issingleton")) {
  65. return parsePerSingleton();
  66. } else if (name.equals("perthis")) {
  67. return parsePerObject(true);
  68. } else if (name.equals("pertarget")) {
  69. return parsePerObject(false);
  70. } else if (name.equals("percflow")) {
  71. return parsePerCflow(false);
  72. } else if (name.equals("percflowbelow")) {
  73. return parsePerCflow(true);
  74. } else if (name.equals("pertypewithin")) { // PTWIMPL Parse the pertypewithin clause
  75. return parsePerTypeWithin();
  76. } else {
  77. return null;
  78. }
  79. }
  80. return null;
  81. }
  82. private PerClause parsePerCflow(boolean isBelow) {
  83. parseIdentifier();
  84. eat("(");
  85. Pointcut entry = parsePointcut();
  86. eat(")");
  87. return new PerCflow(entry, isBelow);
  88. }
  89. private PerClause parsePerObject(boolean isThis) {
  90. parseIdentifier();
  91. eat("(");
  92. Pointcut entry = parsePointcut();
  93. eat(")");
  94. return new PerObject(entry, isThis);
  95. }
  96. private PerClause parsePerTypeWithin() {
  97. parseIdentifier();
  98. eat("(");
  99. TypePattern withinTypePattern = parseTypePattern();
  100. eat(")");
  101. return new PerTypeWithin(withinTypePattern);
  102. }
  103. private PerClause parsePerSingleton() {
  104. parseIdentifier();
  105. eat("(");
  106. eat(")");
  107. return new PerSingleton();
  108. }
  109. public Declare parseDeclare() {
  110. int startPos = tokenSource.peek().getStart();
  111. eatIdentifier("declare");
  112. String kind = parseIdentifier();
  113. Declare ret;
  114. if (kind.equals("error")) {
  115. eat(":");
  116. ret = parseErrorOrWarning(true);
  117. } else if (kind.equals("warning")) {
  118. eat(":");
  119. ret = parseErrorOrWarning(false);
  120. } else if (kind.equals("precedence")) {
  121. eat(":");
  122. ret = parseDominates();
  123. } else if (kind.equals("dominates")) {
  124. throw new ParserException("name changed to declare precedence", tokenSource.peek(-2));
  125. } else if (kind.equals("parents")) {
  126. ret = parseParents();
  127. } else if (kind.equals("soft")) {
  128. eat(":");
  129. ret = parseSoft();
  130. } else {
  131. throw new ParserException(
  132. "expected one of error, warning, parents, soft, precedence, @type, @method, @constructor, @field",
  133. tokenSource.peek(-1));
  134. }
  135. int endPos = tokenSource.peek(-1).getEnd();
  136. ret.setLocation(sourceContext, startPos, endPos);
  137. return ret;
  138. }
  139. public Declare parseDeclareAnnotation() {
  140. int startPos = tokenSource.peek().getStart();
  141. eatIdentifier("declare");
  142. eat("@");
  143. String kind = parseIdentifier();
  144. eat(":");
  145. Declare ret;
  146. if (kind.equals("type")) {
  147. ret = parseDeclareAtType();
  148. } else if (kind.equals("method")) {
  149. ret = parseDeclareAtMethod(true);
  150. } else if (kind.equals("field")) {
  151. ret = parseDeclareAtField();
  152. } else if (kind.equals("constructor")) {
  153. ret = parseDeclareAtMethod(false);
  154. } else {
  155. throw new ParserException("one of type, method, field, constructor", tokenSource.peek(-1));
  156. }
  157. eat(";");
  158. int endPos = tokenSource.peek(-1).getEnd();
  159. ret.setLocation(sourceContext, startPos, endPos);
  160. return ret;
  161. }
  162. public DeclareAnnotation parseDeclareAtType() {
  163. allowHasTypePatterns = true;
  164. TypePattern p = parseTypePattern();
  165. allowHasTypePatterns = false;
  166. return new DeclareAnnotation(DeclareAnnotation.AT_TYPE, p);
  167. }
  168. public DeclareAnnotation parseDeclareAtMethod(boolean isMethod) {
  169. ISignaturePattern sp = parseCompoundMethodOrConstructorSignaturePattern(isMethod);// parseMethodOrConstructorSignaturePattern();
  170. if (!isMethod) {
  171. return new DeclareAnnotation(DeclareAnnotation.AT_CONSTRUCTOR, sp);
  172. } else {
  173. return new DeclareAnnotation(DeclareAnnotation.AT_METHOD, sp);
  174. }
  175. }
  176. public DeclareAnnotation parseDeclareAtField() {
  177. ISignaturePattern compoundFieldSignaturePattern = parseCompoundFieldSignaturePattern();
  178. DeclareAnnotation da = new DeclareAnnotation(DeclareAnnotation.AT_FIELD, compoundFieldSignaturePattern);
  179. return da;
  180. }
  181. public ISignaturePattern parseCompoundFieldSignaturePattern() {
  182. int index = tokenSource.getIndex();
  183. try {
  184. ISignaturePattern atomicFieldSignaturePattern = parseMaybeParenthesizedFieldSignaturePattern();
  185. while (isEitherAndOrOr()) {
  186. if (maybeEat("&&")) {
  187. atomicFieldSignaturePattern = new AndSignaturePattern(atomicFieldSignaturePattern,
  188. parseMaybeParenthesizedFieldSignaturePattern());
  189. }
  190. if (maybeEat("||")) {
  191. atomicFieldSignaturePattern = new OrSignaturePattern(atomicFieldSignaturePattern,
  192. parseMaybeParenthesizedFieldSignaturePattern());
  193. }
  194. }
  195. return atomicFieldSignaturePattern;
  196. } catch (ParserException e) {
  197. // fallback in the case of a regular single field signature pattern that just happened to start with '('
  198. int nowAt = tokenSource.getIndex();
  199. tokenSource.setIndex(index);
  200. try {
  201. ISignaturePattern fsp = parseFieldSignaturePattern();
  202. return fsp;
  203. } catch (Exception e2) {
  204. tokenSource.setIndex(nowAt);
  205. // throw the original
  206. throw e;
  207. }
  208. }
  209. }
  210. private boolean isEitherAndOrOr() {
  211. String tokenstring = tokenSource.peek().getString();
  212. return tokenstring.equals("&&") || tokenstring.equals("||");
  213. }
  214. public ISignaturePattern parseCompoundMethodOrConstructorSignaturePattern(boolean isMethod) {
  215. ISignaturePattern atomicMethodCtorSignaturePattern = parseMaybeParenthesizedMethodOrConstructorSignaturePattern(isMethod);
  216. while (isEitherAndOrOr()) {
  217. if (maybeEat("&&")) {
  218. atomicMethodCtorSignaturePattern = new AndSignaturePattern(atomicMethodCtorSignaturePattern,
  219. parseMaybeParenthesizedMethodOrConstructorSignaturePattern(isMethod));
  220. }
  221. if (maybeEat("||")) {
  222. atomicMethodCtorSignaturePattern = new OrSignaturePattern(atomicMethodCtorSignaturePattern,
  223. parseMaybeParenthesizedMethodOrConstructorSignaturePattern(isMethod));
  224. }
  225. }
  226. return atomicMethodCtorSignaturePattern;
  227. }
  228. public DeclarePrecedence parseDominates() {
  229. List<TypePattern> l = new ArrayList<TypePattern>();
  230. do {
  231. l.add(parseTypePattern());
  232. } while (maybeEat(","));
  233. return new DeclarePrecedence(l);
  234. }
  235. private Declare parseParents() {
  236. /*
  237. * simplified design requires use of raw types for declare parents, no generic spec. allowed String[] typeParameters =
  238. * maybeParseSimpleTypeVariableList();
  239. */
  240. eat(":");
  241. allowHasTypePatterns = true;
  242. TypePattern p = parseTypePattern(false, false);
  243. allowHasTypePatterns = false;
  244. IToken t = tokenSource.next();
  245. if (!(t.getString().equals("extends") || t.getString().equals("implements"))) {
  246. throw new ParserException("extends or implements", t);
  247. }
  248. boolean isExtends = t.getString().equals("extends");
  249. List<TypePattern> l = new ArrayList<TypePattern>();
  250. do {
  251. l.add(parseTypePattern());
  252. } while (maybeEat(","));
  253. // XXX somewhere in the chain we need to enforce that we have only ExactTypePatterns
  254. DeclareParents decp = new DeclareParents(p, l, isExtends);
  255. return decp;
  256. }
  257. private Declare parseSoft() {
  258. TypePattern p = parseTypePattern();
  259. eat(":");
  260. Pointcut pointcut = parsePointcut();
  261. return new DeclareSoft(p, pointcut);
  262. }
  263. /**
  264. * Attempt to parse a pointcut, if that fails then try again for a type pattern.
  265. *
  266. * @param isError true if it is declare error rather than declare warning
  267. * @return the new declare
  268. */
  269. private Declare parseErrorOrWarning(boolean isError) {
  270. Pointcut pointcut = null;
  271. int index = tokenSource.getIndex();
  272. try {
  273. pointcut = parsePointcut();
  274. } catch (ParserException pe) {
  275. try {
  276. tokenSource.setIndex(index);
  277. boolean oldValue = allowHasTypePatterns;
  278. TypePattern typePattern = null;
  279. try {
  280. allowHasTypePatterns = true;
  281. typePattern = parseTypePattern();
  282. } finally {
  283. allowHasTypePatterns = oldValue;
  284. }
  285. eat(":");
  286. String message = parsePossibleStringSequence(true);
  287. return new DeclareTypeErrorOrWarning(isError, typePattern, message);
  288. } catch (ParserException pe2) {
  289. // deliberately throw the original problem
  290. throw pe;
  291. }
  292. }
  293. eat(":");
  294. String message = parsePossibleStringSequence(true);
  295. return new DeclareErrorOrWarning(isError, pointcut, message);
  296. }
  297. public Pointcut parsePointcut() {
  298. Pointcut p = parseAtomicPointcut();
  299. if (maybeEat("&&")) {
  300. p = new AndPointcut(p, parseNotOrPointcut());
  301. }
  302. if (maybeEat("||")) {
  303. p = new OrPointcut(p, parsePointcut());
  304. }
  305. return p;
  306. }
  307. private Pointcut parseNotOrPointcut() {
  308. Pointcut p = parseAtomicPointcut();
  309. if (maybeEat("&&")) {
  310. p = new AndPointcut(p, parseNotOrPointcut());
  311. }
  312. return p;
  313. }
  314. private Pointcut parseAtomicPointcut() {
  315. if (maybeEat("!")) {
  316. int startPos = tokenSource.peek(-1).getStart();
  317. Pointcut p = new NotPointcut(parseAtomicPointcut(), startPos);
  318. return p;
  319. }
  320. if (maybeEat("(")) {
  321. Pointcut p = parsePointcut();
  322. eat(")");
  323. return p;
  324. }
  325. if (maybeEat("@")) {
  326. int startPos = tokenSource.peek().getStart();
  327. Pointcut p = parseAnnotationPointcut();
  328. int endPos = tokenSource.peek(-1).getEnd();
  329. p.setLocation(sourceContext, startPos, endPos);
  330. return p;
  331. }
  332. int startPos = tokenSource.peek().getStart();
  333. Pointcut p = parseSinglePointcut();
  334. int endPos = tokenSource.peek(-1).getEnd();
  335. p.setLocation(sourceContext, startPos, endPos);
  336. return p;
  337. }
  338. public Pointcut parseSinglePointcut() {
  339. int start = tokenSource.getIndex();
  340. IToken t = tokenSource.peek();
  341. Pointcut p = t.maybeGetParsedPointcut();
  342. if (p != null) {
  343. tokenSource.next();
  344. return p;
  345. }
  346. String kind = parseIdentifier();
  347. // IToken possibleTypeVariableToken = tokenSource.peek();
  348. // String[] typeVariables = maybeParseSimpleTypeVariableList();
  349. if (kind.equals("execution") || kind.equals("call") || kind.equals("get") || kind.equals("set")) {
  350. p = parseKindedPointcut(kind);
  351. } else if (kind.equals("args")) {
  352. p = parseArgsPointcut();
  353. } else if (kind.equals("this")) {
  354. p = parseThisOrTargetPointcut(kind);
  355. } else if (kind.equals("target")) {
  356. p = parseThisOrTargetPointcut(kind);
  357. } else if (kind.equals("within")) {
  358. p = parseWithinPointcut();
  359. } else if (kind.equals("withincode")) {
  360. p = parseWithinCodePointcut();
  361. } else if (kind.equals("cflow")) {
  362. p = parseCflowPointcut(false);
  363. } else if (kind.equals("cflowbelow")) {
  364. p = parseCflowPointcut(true);
  365. } else if (kind.equals("adviceexecution")) {
  366. eat("(");
  367. eat(")");
  368. p = new KindedPointcut(Shadow.AdviceExecution, new SignaturePattern(Member.ADVICE, ModifiersPattern.ANY,
  369. TypePattern.ANY, TypePattern.ANY, NamePattern.ANY, TypePatternList.ANY, ThrowsPattern.ANY,
  370. AnnotationTypePattern.ANY));
  371. } else if (kind.equals("handler")) {
  372. eat("(");
  373. TypePattern typePat = parseTypePattern(false, false);
  374. eat(")");
  375. p = new HandlerPointcut(typePat);
  376. } else if (kind.equals("lock") || kind.equals("unlock")) {
  377. p = parseMonitorPointcut(kind);
  378. } else if (kind.equals("initialization")) {
  379. eat("(");
  380. SignaturePattern sig = parseConstructorSignaturePattern();
  381. eat(")");
  382. p = new KindedPointcut(Shadow.Initialization, sig);
  383. } else if (kind.equals("staticinitialization")) {
  384. eat("(");
  385. TypePattern typePat = parseTypePattern(false, false);
  386. eat(")");
  387. p = new KindedPointcut(Shadow.StaticInitialization, new SignaturePattern(Member.STATIC_INITIALIZATION,
  388. ModifiersPattern.ANY, TypePattern.ANY, typePat, NamePattern.ANY, TypePatternList.EMPTY, ThrowsPattern.ANY,
  389. AnnotationTypePattern.ANY));
  390. } else if (kind.equals("preinitialization")) {
  391. eat("(");
  392. SignaturePattern sig = parseConstructorSignaturePattern();
  393. eat(")");
  394. p = new KindedPointcut(Shadow.PreInitialization, sig);
  395. } else if (kind.equals("if")) {
  396. // - annotation style only allows if(), if(true) or if(false)
  397. // - if() means the body of the annotated method represents the if expression
  398. // - anything else is an error because code cannot be put into the if()
  399. // - code style will already have been processed and the call to maybeGetParsedPointcut()
  400. // at the top of this method will have succeeded.
  401. eat("(");
  402. if (maybeEatIdentifier("true")) {
  403. eat(")");
  404. p = new IfPointcut.IfTruePointcut();
  405. } else if (maybeEatIdentifier("false")) {
  406. eat(")");
  407. p = new IfPointcut.IfFalsePointcut();
  408. } else {
  409. if (!maybeEat(")")) {
  410. throw new ParserException(
  411. "in annotation style, if(...) pointcuts cannot contain code. Use if() and put the code in the annotated method",
  412. t);
  413. }
  414. // TODO - Alex has some token stuff going on here to get a readable name in place of ""...
  415. p = new IfPointcut("");
  416. }
  417. } else {
  418. boolean matchedByExtensionDesignator = false;
  419. // see if a registered handler wants to parse it, otherwise
  420. // treat as a reference pointcut
  421. for (PointcutDesignatorHandler pcd : pointcutDesignatorHandlers) {
  422. if (pcd.getDesignatorName().equals(kind)) {
  423. p = parseDesignatorPointcut(pcd);
  424. matchedByExtensionDesignator = true;
  425. }
  426. }
  427. if (!matchedByExtensionDesignator) {
  428. tokenSource.setIndex(start);
  429. p = parseReferencePointcut();
  430. }
  431. }
  432. return p;
  433. }
  434. private void assertNoTypeVariables(String[] tvs, String errorMessage, IToken token) {
  435. if (tvs != null) {
  436. throw new ParserException(errorMessage, token);
  437. }
  438. }
  439. public Pointcut parseAnnotationPointcut() {
  440. int start = tokenSource.getIndex();
  441. IToken t = tokenSource.peek();
  442. String kind = parseIdentifier();
  443. IToken possibleTypeVariableToken = tokenSource.peek();
  444. String[] typeVariables = maybeParseSimpleTypeVariableList();
  445. if (typeVariables != null) {
  446. String message = "(";
  447. assertNoTypeVariables(typeVariables, message, possibleTypeVariableToken);
  448. }
  449. tokenSource.setIndex(start);
  450. if (kind.equals("annotation")) {
  451. return parseAtAnnotationPointcut();
  452. } else if (kind.equals("args")) {
  453. return parseArgsAnnotationPointcut();
  454. } else if (kind.equals("this") || kind.equals("target")) {
  455. return parseThisOrTargetAnnotationPointcut();
  456. } else if (kind.equals("within")) {
  457. return parseWithinAnnotationPointcut();
  458. } else if (kind.equals("withincode")) {
  459. return parseWithinCodeAnnotationPointcut();
  460. }
  461. throw new ParserException("pointcut name", t);
  462. }
  463. private Pointcut parseAtAnnotationPointcut() {
  464. parseIdentifier();
  465. eat("(");
  466. if (maybeEat(")")) {
  467. throw new ParserException("@AnnotationName or parameter", tokenSource.peek());
  468. }
  469. ExactAnnotationTypePattern type = parseAnnotationNameOrVarTypePattern();
  470. eat(")");
  471. return new AnnotationPointcut(type);
  472. }
  473. private SignaturePattern parseConstructorSignaturePattern() {
  474. SignaturePattern ret = parseMethodOrConstructorSignaturePattern();
  475. if (ret.getKind() == Member.CONSTRUCTOR) {
  476. return ret;
  477. }
  478. throw new ParserException("constructor pattern required, found method pattern", ret);
  479. }
  480. private Pointcut parseWithinCodePointcut() {
  481. // parseIdentifier();
  482. eat("(");
  483. SignaturePattern sig = parseMethodOrConstructorSignaturePattern();
  484. eat(")");
  485. return new WithincodePointcut(sig);
  486. }
  487. private Pointcut parseCflowPointcut(boolean isBelow) {
  488. // parseIdentifier();
  489. eat("(");
  490. Pointcut entry = parsePointcut();
  491. eat(")");
  492. return new CflowPointcut(entry, isBelow, null);
  493. }
  494. /**
  495. * Method parseWithinPointcut.
  496. *
  497. * @return Pointcut
  498. */
  499. private Pointcut parseWithinPointcut() {
  500. // parseIdentifier();
  501. eat("(");
  502. TypePattern type = parseTypePattern();
  503. eat(")");
  504. return new WithinPointcut(type);
  505. }
  506. /**
  507. * Method parseThisOrTargetPointcut.
  508. *
  509. * @return Pointcut
  510. */
  511. private Pointcut parseThisOrTargetPointcut(String kind) {
  512. boolean optional = false;
  513. if (maybeEat("?")) {
  514. optional = true;
  515. }
  516. eat("(");
  517. TypePattern type = parseTypePattern();
  518. eat(")");
  519. return new ThisOrTargetPointcut(kind.equals("this"), type,optional);
  520. }
  521. private Pointcut parseThisOrTargetAnnotationPointcut() {
  522. String kind = parseIdentifier();
  523. eat("(");
  524. if (maybeEat(")")) {
  525. throw new ParserException("expecting @AnnotationName or parameter, but found ')'", tokenSource.peek());
  526. }
  527. ExactAnnotationTypePattern type = parseAnnotationNameOrVarTypePattern();
  528. eat(")");
  529. return new ThisOrTargetAnnotationPointcut(kind.equals("this"), type);
  530. }
  531. private Pointcut parseWithinAnnotationPointcut() {
  532. /* String kind = */parseIdentifier();
  533. eat("(");
  534. if (maybeEat(")")) {
  535. throw new ParserException("expecting @AnnotationName or parameter, but found ')'", tokenSource.peek());
  536. }
  537. AnnotationTypePattern type = parseAnnotationNameOrVarTypePattern();
  538. eat(")");
  539. return new WithinAnnotationPointcut(type);
  540. }
  541. private Pointcut parseWithinCodeAnnotationPointcut() {
  542. /* String kind = */parseIdentifier();
  543. eat("(");
  544. if (maybeEat(")")) {
  545. throw new ParserException("expecting @AnnotationName or parameter, but found ')'", tokenSource.peek());
  546. }
  547. ExactAnnotationTypePattern type = parseAnnotationNameOrVarTypePattern();
  548. eat(")");
  549. return new WithinCodeAnnotationPointcut(type);
  550. }
  551. /**
  552. * Method parseArgsPointcut.
  553. *
  554. * @return Pointcut
  555. */
  556. private Pointcut parseArgsPointcut() {
  557. // parseIdentifier();
  558. TypePatternList arguments = parseArgumentsPattern(false);
  559. return new ArgsPointcut(arguments);
  560. }
  561. private Pointcut parseArgsAnnotationPointcut() {
  562. parseIdentifier();
  563. AnnotationPatternList arguments = parseArgumentsAnnotationPattern();
  564. return new ArgsAnnotationPointcut(arguments);
  565. }
  566. private Pointcut parseReferencePointcut() {
  567. TypePattern onType = parseTypePattern();
  568. NamePattern name = null;
  569. if (onType.typeParameters.size() > 0) {
  570. eat(".");
  571. name = parseNamePattern();
  572. } else {
  573. name = tryToExtractName(onType);
  574. }
  575. if (name == null) {
  576. throw new ParserException("name pattern", tokenSource.peek());
  577. }
  578. if (onType.toString().equals("")) {
  579. onType = null;
  580. }
  581. String simpleName = name.maybeGetSimpleName();
  582. if (simpleName == null) {
  583. throw new ParserException("(", tokenSource.peek(-1));
  584. }
  585. TypePatternList arguments = parseArgumentsPattern(false);
  586. return new ReferencePointcut(onType, simpleName, arguments);
  587. }
  588. private Pointcut parseDesignatorPointcut(PointcutDesignatorHandler pcdHandler) {
  589. eat("(");
  590. int parenCount = 1;
  591. StringBuffer pointcutBody = new StringBuffer();
  592. while (parenCount > 0) {
  593. if (maybeEat("(")) {
  594. parenCount++;
  595. pointcutBody.append("(");
  596. } else if (maybeEat(")")) {
  597. parenCount--;
  598. if (parenCount > 0) {
  599. pointcutBody.append(")");
  600. }
  601. } else {
  602. pointcutBody.append(nextToken().getString());
  603. }
  604. }
  605. ContextBasedMatcher pcExpr = pcdHandler.parse(pointcutBody.toString());
  606. return new PointcutDesignatorHandlerBasedPointcut(pcExpr, world);
  607. }
  608. public List<String> parseDottedIdentifier() {
  609. List<String> ret = new ArrayList<String>();
  610. ret.add(parseIdentifier());
  611. while (maybeEat(".")) {
  612. ret.add(parseIdentifier());
  613. }
  614. return ret;
  615. }
  616. private KindedPointcut parseKindedPointcut(String kind) {
  617. eat("(");
  618. SignaturePattern sig;
  619. Shadow.Kind shadowKind = null;
  620. if (kind.equals("execution")) {
  621. sig = parseMethodOrConstructorSignaturePattern();
  622. if (sig.getKind() == Member.METHOD) {
  623. shadowKind = Shadow.MethodExecution;
  624. } else if (sig.getKind() == Member.CONSTRUCTOR) {
  625. shadowKind = Shadow.ConstructorExecution;
  626. }
  627. } else if (kind.equals("call")) {
  628. sig = parseMethodOrConstructorSignaturePattern();
  629. if (sig.getKind() == Member.METHOD) {
  630. shadowKind = Shadow.MethodCall;
  631. } else if (sig.getKind() == Member.CONSTRUCTOR) {
  632. shadowKind = Shadow.ConstructorCall;
  633. }
  634. } else if (kind.equals("get")) {
  635. sig = parseFieldSignaturePattern();
  636. shadowKind = Shadow.FieldGet;
  637. } else if (kind.equals("set")) {
  638. sig = parseFieldSignaturePattern();
  639. shadowKind = Shadow.FieldSet;
  640. } else {
  641. throw new ParserException("bad kind: " + kind, tokenSource.peek());
  642. }
  643. eat(")");
  644. return new KindedPointcut(shadowKind, sig);
  645. }
  646. /** Covers the 'lock()' and 'unlock()' pointcuts */
  647. private KindedPointcut parseMonitorPointcut(String kind) {
  648. eat("(");
  649. // TypePattern type = TypePattern.ANY;
  650. eat(")");
  651. if (kind.equals("lock")) {
  652. return new KindedPointcut(Shadow.SynchronizationLock, new SignaturePattern(Member.MONITORENTER, ModifiersPattern.ANY,
  653. TypePattern.ANY, TypePattern.ANY,
  654. // type,
  655. NamePattern.ANY, TypePatternList.ANY, ThrowsPattern.ANY, AnnotationTypePattern.ANY));
  656. } else {
  657. return new KindedPointcut(Shadow.SynchronizationUnlock, new SignaturePattern(Member.MONITORENTER, ModifiersPattern.ANY,
  658. TypePattern.ANY, TypePattern.ANY,
  659. // type,
  660. NamePattern.ANY, TypePatternList.ANY, ThrowsPattern.ANY, AnnotationTypePattern.ANY));
  661. }
  662. }
  663. public TypePattern parseTypePattern() {
  664. return parseTypePattern(false, false);
  665. }
  666. public TypePattern parseTypePattern(boolean insideTypeParameters, boolean parameterAnnotationsPossible) {
  667. TypePattern p = parseAtomicTypePattern(insideTypeParameters, parameterAnnotationsPossible);
  668. if (maybeEat("&&")) {
  669. p = new AndTypePattern(p, parseNotOrTypePattern(insideTypeParameters, parameterAnnotationsPossible));
  670. }
  671. if (maybeEat("||")) {
  672. p = new OrTypePattern(p, parseTypePattern(insideTypeParameters, parameterAnnotationsPossible));
  673. }
  674. return p;
  675. }
  676. private TypePattern parseNotOrTypePattern(boolean insideTypeParameters, boolean parameterAnnotationsPossible) {
  677. TypePattern p = parseAtomicTypePattern(insideTypeParameters, parameterAnnotationsPossible);
  678. if (maybeEat("&&")) {
  679. p = new AndTypePattern(p, parseTypePattern(insideTypeParameters, parameterAnnotationsPossible));
  680. }
  681. return p;
  682. }
  683. // Need to differentiate in here between two kinds of annotation pattern - depending on where the ( is
  684. private TypePattern parseAtomicTypePattern(boolean insideTypeParameters, boolean parameterAnnotationsPossible) {
  685. AnnotationTypePattern ap = maybeParseAnnotationPattern(); // might be parameter annotation pattern or type annotation
  686. // pattern
  687. if (maybeEat("!")) {
  688. // int startPos = tokenSource.peek(-1).getStart();
  689. // ??? we lose source location for true start of !type
  690. // An annotation, if processed, is outside of the Not - so here we have to build
  691. // an And pattern containing the annotation and the not as left and right children
  692. // *unless* the annotation pattern was just 'Any' then we can skip building the
  693. // And and just return the Not directly (pr228980)
  694. TypePattern p = null;
  695. TypePattern tp = parseAtomicTypePattern(insideTypeParameters, parameterAnnotationsPossible);
  696. if (!(ap instanceof AnyAnnotationTypePattern)) {
  697. p = new NotTypePattern(tp);
  698. p = new AndTypePattern(setAnnotationPatternForTypePattern(TypePattern.ANY, ap, false), p);
  699. } else {
  700. p = new NotTypePattern(tp);
  701. }
  702. return p;
  703. }
  704. if (maybeEat("(")) {
  705. int openParenPos = tokenSource.peek(-1).getStart();
  706. TypePattern p = parseTypePattern(insideTypeParameters, false);
  707. if ((p instanceof NotTypePattern) && !(ap instanceof AnyAnnotationTypePattern)) {
  708. // dont set the annotation on it, we don't want the annotation to be
  709. // considered as part of the not, it is outside the not (pr228980)
  710. TypePattern tp = setAnnotationPatternForTypePattern(TypePattern.ANY, ap, parameterAnnotationsPossible);
  711. p = new AndTypePattern(tp, p);
  712. } else {
  713. p = setAnnotationPatternForTypePattern(p, ap, parameterAnnotationsPossible);
  714. }
  715. eat(")");
  716. int closeParenPos = tokenSource.peek(-1).getStart();
  717. boolean isVarArgs = maybeEat("...");
  718. if (isVarArgs) {
  719. p.setIsVarArgs(isVarArgs);
  720. }
  721. boolean isIncludeSubtypes = maybeEat("+");
  722. if (isIncludeSubtypes) {
  723. p.includeSubtypes = true; // need the test because (A+) should not set subtypes to false!
  724. }
  725. p.start = openParenPos;
  726. p.end = closeParenPos;
  727. return p;
  728. }
  729. int startPos = tokenSource.peek().getStart();
  730. if (ap.start != -1) {
  731. startPos = ap.start;
  732. }
  733. TypePattern p = parseSingleTypePattern(insideTypeParameters);
  734. int endPos = tokenSource.peek(-1).getEnd();
  735. p = setAnnotationPatternForTypePattern(p, ap, false);
  736. p.setLocation(sourceContext, startPos, endPos);
  737. return p;
  738. }
  739. private TypePattern setAnnotationPatternForTypePattern(TypePattern t, AnnotationTypePattern ap,
  740. boolean parameterAnnotationsPattern) {
  741. TypePattern ret = t;
  742. if (parameterAnnotationsPattern) {
  743. ap.setForParameterAnnotationMatch();
  744. }
  745. if (ap != AnnotationTypePattern.ANY) {
  746. if (t == TypePattern.ANY) {
  747. if (t.annotationPattern == AnnotationTypePattern.ANY) {
  748. return new AnyWithAnnotationTypePattern(ap);
  749. } else {
  750. return new AnyWithAnnotationTypePattern(new AndAnnotationTypePattern(ap, t.annotationPattern));
  751. }
  752. // ret = new WildTypePattern(new NamePattern[] { NamePattern.ANY }, false, 0, false, null);
  753. }
  754. if (t.annotationPattern == AnnotationTypePattern.ANY) {
  755. ret.setAnnotationTypePattern(ap);
  756. } else {
  757. ret.setAnnotationTypePattern(new AndAnnotationTypePattern(ap, t.annotationPattern)); // ???
  758. }
  759. }
  760. return ret;
  761. }
  762. public AnnotationTypePattern maybeParseAnnotationPattern() {
  763. AnnotationTypePattern ret = AnnotationTypePattern.ANY;
  764. AnnotationTypePattern nextPattern = null;
  765. while ((nextPattern = maybeParseSingleAnnotationPattern()) != null) {
  766. if (ret == AnnotationTypePattern.ANY) {
  767. ret = nextPattern;
  768. } else {
  769. ret = new AndAnnotationTypePattern(ret, nextPattern);
  770. }
  771. }
  772. return ret;
  773. }
  774. // PVAL cope with annotation values at other places in this code
  775. public AnnotationTypePattern maybeParseSingleAnnotationPattern() {
  776. AnnotationTypePattern ret = null;
  777. Map<String, String> values = null;
  778. // LALR(2) - fix by making "!@" a single token
  779. int startIndex = tokenSource.getIndex();
  780. if (maybeEat("!")) {
  781. if (maybeEat("@")) {
  782. if (maybeEat("(")) {
  783. TypePattern p = parseTypePattern();
  784. ret = new NotAnnotationTypePattern(new WildAnnotationTypePattern(p));
  785. eat(")");
  786. return ret;
  787. } else {
  788. TypePattern p = parseSingleTypePattern();
  789. if (maybeEatAdjacent("(")) {
  790. values = parseAnnotationValues();
  791. eat(")");
  792. ret = new NotAnnotationTypePattern(new WildAnnotationTypePattern(p, values));
  793. } else {
  794. ret = new NotAnnotationTypePattern(new WildAnnotationTypePattern(p));
  795. }
  796. return ret;
  797. }
  798. } else {
  799. tokenSource.setIndex(startIndex); // not for us!
  800. return ret;
  801. }
  802. }
  803. if (maybeEat("@")) {
  804. if (maybeEat("(")) {
  805. TypePattern p = parseTypePattern();
  806. ret = new WildAnnotationTypePattern(p);
  807. eat(")");
  808. return ret;
  809. } else {
  810. int atPos = tokenSource.peek(-1).getStart();
  811. TypePattern p = parseSingleTypePattern();
  812. if (maybeEatAdjacent("(")) {
  813. values = parseAnnotationValues();
  814. eat(")");
  815. ret = new WildAnnotationTypePattern(p, values);
  816. } else {
  817. ret = new WildAnnotationTypePattern(p);
  818. }
  819. ret.start = atPos;
  820. return ret;
  821. }
  822. } else {
  823. tokenSource.setIndex(startIndex); // not for us!
  824. return ret;
  825. }
  826. }
  827. // Parse annotation values. In an expression in @A(a=b,c=d) this method will be
  828. // parsing the a=b,c=d.)
  829. public Map<String, String> parseAnnotationValues() {
  830. Map<String, String> values = new HashMap<String, String>();
  831. boolean seenDefaultValue = false;
  832. do {
  833. String possibleKeyString = parseAnnotationNameValuePattern();
  834. if (possibleKeyString == null) {
  835. throw new ParserException("expecting simple literal ", tokenSource.peek(-1));
  836. }
  837. // did they specify just a single entry 'v' or a keyvalue pair 'k=v'
  838. if (maybeEat("=")) {
  839. // it was a key!
  840. String valueString = parseAnnotationNameValuePattern();
  841. if (valueString == null) {
  842. throw new ParserException("expecting simple literal ", tokenSource.peek(-1));
  843. }
  844. values.put(possibleKeyString, valueString);
  845. } else if (maybeEat("!=")) {
  846. // it was a key, with a !=
  847. String valueString = parseAnnotationNameValuePattern();
  848. if (valueString == null) {
  849. throw new ParserException("expecting simple literal ", tokenSource.peek(-1));
  850. }
  851. // negation is captured by adding a trailing ! to the key name
  852. values.put(possibleKeyString + "!", valueString);
  853. } else {
  854. if (seenDefaultValue) {
  855. throw new ParserException("cannot specify two default values", tokenSource.peek(-1));
  856. }
  857. seenDefaultValue = true;
  858. values.put("value", possibleKeyString);
  859. }
  860. } while (maybeEat(",")); // keep going whilst there are ','
  861. return values;
  862. }
  863. public TypePattern parseSingleTypePattern() {
  864. return parseSingleTypePattern(false);
  865. }
  866. public TypePattern parseSingleTypePattern(boolean insideTypeParameters) {
  867. if (insideTypeParameters && maybeEat("?")) {
  868. return parseGenericsWildcardTypePattern();
  869. }
  870. if (allowHasTypePatterns) {
  871. if (maybeEatIdentifier("hasmethod")) {
  872. return parseHasMethodTypePattern();
  873. }
  874. if (maybeEatIdentifier("hasfield")) {
  875. return parseHasFieldTypePattern();
  876. }
  877. }
  878. // // Check for a type category
  879. // IToken token = tokenSource.peek();
  880. // if (token.isIdentifier()) {
  881. // String category = token.getString();
  882. // TypeCategoryTypePattern typeIsPattern = null;
  883. // if (category.equals("isClass")) {
  884. // typeIsPattern = new TypeCategoryTypePattern(TypeCategoryTypePattern.CLASS);
  885. // } else if (category.equals("isAspect")) {
  886. // typeIsPattern = new TypeCategoryTypePattern(TypeCategoryTypePattern.ASPECT);
  887. // } else if (category.equals("isInterface")) {
  888. // typeIsPattern = new TypeCategoryTypePattern(TypeCategoryTypePattern.INTERFACE);
  889. // } else if (category.equals("isInner")) {
  890. // typeIsPattern = new TypeCategoryTypePattern(TypeCategoryTypePattern.INNER);
  891. // } else if (category.equals("isAnonymous")) {
  892. // typeIsPattern = new TypeCategoryTypePattern(TypeCategoryTypePattern.ANONYMOUS);
  893. // } else if (category.equals("isEnum")) {
  894. // typeIsPattern = new TypeCategoryTypePattern(TypeCategoryTypePattern.ENUM);
  895. // } else if (category.equals("isAnnotation")) {
  896. // typeIsPattern = new TypeCategoryTypePattern(TypeCategoryTypePattern.ANNOTATION);
  897. // }
  898. // if (typeIsPattern != null) {
  899. // tokenSource.next();
  900. // typeIsPattern.setLocation(tokenSource.getSourceContext(), token.getStart(), token.getEnd());
  901. // return typeIsPattern;
  902. // }
  903. // }
  904. if (maybeEatIdentifier("is")) {
  905. int pos = tokenSource.getIndex() - 1;
  906. TypePattern typeIsPattern = parseIsTypePattern();
  907. if (typeIsPattern != null) {
  908. return typeIsPattern;
  909. }
  910. // rewind as if we never tried to parse it as a typeIs
  911. tokenSource.setIndex(pos);
  912. }
  913. List<NamePattern> names = parseDottedNamePattern();
  914. int dim = 0;
  915. while (maybeEat("[")) {
  916. eat("]");
  917. dim++;
  918. }
  919. TypePatternList typeParameters = maybeParseTypeParameterList();
  920. int endPos = tokenSource.peek(-1).getEnd();
  921. boolean includeSubtypes = maybeEat("+");
  922. // TODO do we need to associate the + with either the type or the array?
  923. while (maybeEat("[")) {
  924. eat("]");
  925. dim++;
  926. }
  927. boolean isVarArgs = maybeEat("...");
  928. // ??? what about the source location of any's????
  929. if (names.size() == 1 && names.get(0).isAny() && dim == 0 && !isVarArgs && typeParameters == null) {
  930. return TypePattern.ANY;
  931. }
  932. // Notice we increase the dimensions if varargs is set. this is to allow type matching to
  933. // succeed later: The actual signature at runtime of a method declared varargs is an array type of
  934. // the original declared type (so Integer... becomes Integer[] in the bytecode). So, here for the
  935. // pattern 'Integer...' we create a WildTypePattern 'Integer[]' with varargs set. If this matches
  936. // during shadow matching, we confirm that the varargs flags match up before calling it a successful
  937. // match.
  938. return new WildTypePattern(names, includeSubtypes, dim + (isVarArgs ? 1 : 0), endPos, isVarArgs, typeParameters);
  939. }
  940. public TypePattern parseHasMethodTypePattern() {
  941. int startPos = tokenSource.peek(-1).getStart();
  942. eat("(");
  943. SignaturePattern sp = parseMethodOrConstructorSignaturePattern();
  944. eat(")");
  945. int endPos = tokenSource.peek(-1).getEnd();
  946. HasMemberTypePattern ret = new HasMemberTypePattern(sp);
  947. ret.setLocation(sourceContext, startPos, endPos);
  948. return ret;
  949. }
  950. /**
  951. * Attempt to parse a typeIs(<category>) construct. If it cannot be parsed we just return null and that should cause the caller
  952. * to reset their position and attempt to consume it in another way. This means we won't have problems here: execution(*
  953. * typeIs(..)) because someone has decided to call a method the same as our construct.
  954. *
  955. * @return a TypeIsTypePattern or null if could not be parsed
  956. */
  957. public TypePattern parseIsTypePattern() {
  958. int startPos = tokenSource.peek(-1).getStart(); // that will be the start of the 'typeIs'
  959. if (!maybeEatAdjacent("(")) {
  960. return null;
  961. }
  962. IToken token = tokenSource.next();
  963. TypeCategoryTypePattern typeIsPattern = null;
  964. if (token.isIdentifier()) {
  965. String category = token.getString();
  966. if (category.equals("ClassType")) {
  967. typeIsPattern = new TypeCategoryTypePattern(TypeCategoryTypePattern.CLASS);
  968. } else if (category.equals("AspectType")) {
  969. typeIsPattern = new TypeCategoryTypePattern(TypeCategoryTypePattern.ASPECT);
  970. } else if (category.equals("InterfaceType")) {
  971. typeIsPattern = new TypeCategoryTypePattern(TypeCategoryTypePattern.INTERFACE);
  972. } else if (category.equals("InnerType")) {
  973. typeIsPattern = new TypeCategoryTypePattern(TypeCategoryTypePattern.INNER);
  974. } else if (category.equals("AnonymousType")) {
  975. typeIsPattern = new TypeCategoryTypePattern(TypeCategoryTypePattern.ANONYMOUS);
  976. } else if (category.equals("EnumType")) {
  977. typeIsPattern = new TypeCategoryTypePattern(TypeCategoryTypePattern.ENUM);
  978. } else if (category.equals("AnnotationType")) {
  979. typeIsPattern = new TypeCategoryTypePattern(TypeCategoryTypePattern.ANNOTATION);
  980. }
  981. }
  982. if (typeIsPattern == null) {
  983. return null;
  984. }
  985. if (!maybeEat(")")) {
  986. throw new ParserException(")", tokenSource.peek());
  987. }
  988. int endPos = tokenSource.peek(-1).getEnd();
  989. typeIsPattern.setLocation(tokenSource.getSourceContext(), startPos, endPos);
  990. return typeIsPattern;
  991. }
  992. // if (names.size() == 1 && !names.get(0).isAny()) {
  993. // if (maybeEatAdjacent("(")) {
  994. // if (maybeEat(")")) {
  995. // // likely to be one of isClass()/isInterface()/isInner()/isAnonymous()/isAspect()
  996. // if (names.size() == 1) {
  997. // NamePattern np = names.get(0);
  998. // String simpleName = np.maybeGetSimpleName();
  999. // if (simpleName != null) {
  1000. // return new TypeCategoryTypePattern(TypeCategoryTypePattern.ANNOTATION, np);
  1001. // } else {
  1002. // throw new ParserException(
  1003. // "not a supported type category, supported are isClass/isInterface/isEnum/isAnnotation/isInner/isAnonymous",
  1004. // tokenSource.peek(-3));
  1005. // }
  1006. // }
  1007. // int stop = 1;
  1008. // // return new WildTypePattern(names, includeSubtypes, dim + (isVarArgs ? 1 : 0), endPos, isVarArgs,
  1009. // // typeParameters);
  1010. // }
  1011. // } else {
  1012. // throw new ParserException("category type pattern is missing closing parentheses", tokenSource.peek(-2));
  1013. // }
  1014. // }
  1015. // }
  1016. public TypePattern parseHasFieldTypePattern() {
  1017. int startPos = tokenSource.peek(-1).getStart();
  1018. eat("(");
  1019. SignaturePattern sp = parseFieldSignaturePattern();
  1020. eat(")");
  1021. int endPos = tokenSource.peek(-1).getEnd();
  1022. HasMemberTypePattern ret = new HasMemberTypePattern(sp);
  1023. ret.setLocation(sourceContext, startPos, endPos);
  1024. return ret;
  1025. }
  1026. public TypePattern parseGenericsWildcardTypePattern() {
  1027. List<NamePattern> names = new ArrayList<NamePattern>();
  1028. names.add(new NamePattern("?"));
  1029. TypePattern upperBound = null;
  1030. TypePattern[] additionalInterfaceBounds = new TypePattern[0];
  1031. TypePattern lowerBound = null;
  1032. if (maybeEatIdentifier("extends")) {
  1033. upperBound = parseTypePattern(false, false);
  1034. additionalInterfaceBounds = maybeParseAdditionalInterfaceBounds();
  1035. }
  1036. if (maybeEatIdentifier("super")) {
  1037. lowerBound = parseTypePattern(false, false);
  1038. }
  1039. int endPos = tokenSource.peek(-1).getEnd();
  1040. return new WildTypePattern(names, false, 0, endPos, false, null, upperBound, additionalInterfaceBounds, lowerBound);
  1041. }
  1042. // private AnnotationTypePattern completeAnnotationPattern(AnnotationTypePattern p) {
  1043. // if (maybeEat("&&")) {
  1044. // return new AndAnnotationTypePattern(p,parseNotOrAnnotationPattern());
  1045. // }
  1046. // if (maybeEat("||")) {
  1047. // return new OrAnnotationTypePattern(p,parseAnnotationTypePattern());
  1048. // }
  1049. // return p;
  1050. // }
  1051. //
  1052. // protected AnnotationTypePattern parseAnnotationTypePattern() {
  1053. // AnnotationTypePattern ap = parseAtomicAnnotationPattern();
  1054. // if (maybeEat("&&")) {
  1055. // ap = new AndAnnotationTypePattern(ap, parseNotOrAnnotationPattern());
  1056. // }
  1057. //
  1058. // if (maybeEat("||")) {
  1059. // ap = new OrAnnotationTypePattern(ap, parseAnnotationTypePattern());
  1060. // }
  1061. // return ap;
  1062. // }
  1063. //
  1064. // private AnnotationTypePattern parseNotOrAnnotationPattern() {
  1065. // AnnotationTypePattern p = parseAtomicAnnotationPattern();
  1066. // if (maybeEat("&&")) {
  1067. // p = new AndAnnotationTypePattern(p,parseAnnotationTypePattern());
  1068. // }
  1069. // return p;
  1070. // }
  1071. protected ExactAnnotationTypePattern parseAnnotationNameOrVarTypePattern() {
  1072. ExactAnnotationTypePattern p = null;
  1073. int startPos = tokenSource.peek().getStart();
  1074. if (maybeEat("@")) {
  1075. throw new ParserException("@Foo form was deprecated in AspectJ 5 M2: annotation name or var ", tokenSource.peek(-1));
  1076. }
  1077. p = parseSimpleAnnotationName();
  1078. int endPos = tokenSource.peek(-1).getEnd();
  1079. p.setLocation(sourceContext, startPos, endPos);
  1080. // For optimized syntax that allows binding directly to annotation values (pr234943)
  1081. if (maybeEat("(")) {
  1082. String formalName = parseIdentifier();
  1083. p = new ExactAnnotationFieldTypePattern(p, formalName);
  1084. eat(")");
  1085. }
  1086. return p;
  1087. }
  1088. /**
  1089. * @return
  1090. */
  1091. private ExactAnnotationTypePattern parseSimpleAnnotationName() {
  1092. // the @ has already been eaten...
  1093. ExactAnnotationTypePattern p;
  1094. StringBuffer annotationName = new StringBuffer();
  1095. annotationName.append(parseIdentifier());
  1096. while (maybeEat(".")) {
  1097. annotationName.append('.');
  1098. annotationName.append(parseIdentifier());
  1099. }
  1100. UnresolvedType type = UnresolvedType.forName(annotationName.toString());
  1101. p = new ExactAnnotationTypePattern(type, null);
  1102. return p;
  1103. }
  1104. // private AnnotationTypePattern parseAtomicAnnotationPattern() {
  1105. // if (maybeEat("!")) {
  1106. // //int startPos = tokenSource.peek(-1).getStart();
  1107. // //??? we lose source location for true start of !type
  1108. // AnnotationTypePattern p = new NotAnnotationTypePattern(parseAtomicAnnotationPattern());
  1109. // return p;
  1110. // }
  1111. // if (maybeEat("(")) {
  1112. // AnnotationTypePattern p = parseAnnotationTypePattern();
  1113. // eat(")");
  1114. // return p;
  1115. // }
  1116. // int startPos = tokenSource.peek().getStart();
  1117. // eat("@");
  1118. // StringBuffer annotationName = new StringBuffer();
  1119. // annotationName.append(parseIdentifier());
  1120. // while (maybeEat(".")) {
  1121. // annotationName.append('.');
  1122. // annotationName.append(parseIdentifier());
  1123. // }
  1124. // UnresolvedType type = UnresolvedType.forName(annotationName.toString());
  1125. // AnnotationTypePattern p = new ExactAnnotationTypePattern(type);
  1126. // int endPos = tokenSource.peek(-1).getEnd();
  1127. // p.setLocation(sourceContext, startPos, endPos);
  1128. // return p;
  1129. // }
  1130. public List<NamePattern> parseDottedNamePattern() {
  1131. List<NamePattern> names = new ArrayList<NamePattern>();
  1132. StringBuffer buf = new StringBuffer();
  1133. IToken previous = null;
  1134. boolean justProcessedEllipsis = false; // Remember if we just dealt with an ellipsis (PR61536)
  1135. boolean justProcessedDot = false;
  1136. boolean onADot = false;
  1137. while (true) {
  1138. IToken tok = null;
  1139. int startPos = tokenSource.peek().getStart();
  1140. String afterDot = null;
  1141. while (true) {
  1142. if (previous != null && previous.getString().equals(".")) {
  1143. justProcessedDot = true;
  1144. }
  1145. tok = tokenSource.peek();
  1146. onADot = (tok.getString().equals("."));
  1147. if (previous != null) {
  1148. if (!isAdjacent(previous, tok)) {
  1149. break;
  1150. }
  1151. }
  1152. if (tok.getString() == "*" || (tok.isIdentifier() && tok.getString() != "...")) {
  1153. buf.append(tok.getString());
  1154. } else if (tok.getString() == "...") {
  1155. break;
  1156. } else if (tok.getLiteralKind() != null) {
  1157. // System.err.println("literal kind: " + tok.getString());
  1158. String s = tok.getString();
  1159. int dot = s.indexOf('.');
  1160. if (dot != -1) {
  1161. buf.append(s.substring(0, dot));
  1162. afterDot = s.substring(dot + 1);
  1163. previous = tokenSource.next();
  1164. break;
  1165. }
  1166. buf.append(s); // ??? so-so
  1167. } else {
  1168. break;
  1169. }
  1170. previous = tokenSource.next();
  1171. // XXX need to handle floats and other fun stuff
  1172. }
  1173. int endPos = tokenSource.peek(-1).getEnd();
  1174. if (buf.length() == 0 && names.isEmpty()) {
  1175. throw new ParserException("name pattern", tok);
  1176. }
  1177. if (buf.length() == 0 && justProcessedEllipsis) {
  1178. throw new ParserException("name pattern cannot finish with ..", tok);
  1179. }
  1180. if (buf.length() == 0 && justProcessedDot && !onADot) {
  1181. throw new ParserException("name pattern cannot finish with .", tok);
  1182. }
  1183. if (buf.length() == 0) {
  1184. names.add(NamePattern.ELLIPSIS);
  1185. justProcessedEllipsis = true;
  1186. } else {
  1187. checkLegalName(buf.toString(), previous);
  1188. NamePattern ret = new NamePattern(buf.toString());
  1189. ret.setLocation(sourceContext, startPos, endPos);
  1190. names.add(ret);
  1191. justProcessedEllipsis = false;
  1192. }
  1193. if (afterDot == null) {
  1194. buf.setLength(0);
  1195. // no elipsis or dotted name part
  1196. if (!maybeEat(".")) {
  1197. break;
  1198. // go on
  1199. } else {
  1200. previous = tokenSource.peek(-1);
  1201. }
  1202. } else {
  1203. buf.setLength(0);
  1204. buf.append(afterDot);
  1205. afterDot = null;
  1206. }
  1207. }
  1208. // System.err.println("parsed: " + names);
  1209. return names;
  1210. }
  1211. // supported form 'a.b.c.d' or just 'a'
  1212. public String parseAnnotationNameValuePattern() {
  1213. StringBuffer buf = new StringBuffer();
  1214. IToken tok;
  1215. // int startPos =
  1216. tokenSource.peek().getStart();
  1217. boolean dotOK = false;
  1218. int depth = 0;
  1219. while (true) {
  1220. tok = tokenSource.peek();
  1221. // keep going until we hit ')' or '=' or ','
  1222. if (tok.getString() == ")" && depth == 0) {
  1223. break;
  1224. }
  1225. if (tok.getString() == "!=" && depth == 0) {
  1226. break;
  1227. }
  1228. if (tok.getString() == "=" && depth == 0) {
  1229. break;
  1230. }
  1231. if (tok.getString() == "," && depth == 0) {
  1232. break;
  1233. }
  1234. if (tok == IToken.EOF) {
  1235. throw new ParserException("eof", tokenSource.peek());
  1236. }
  1237. // keep track of nested brackets
  1238. if (tok.getString() == "(") {
  1239. depth++;
  1240. }
  1241. if (tok.getString() == ")") {
  1242. depth--;
  1243. }
  1244. if (tok.getString() == "{") {
  1245. depth++;
  1246. }
  1247. if (tok.getString() == "}") {
  1248. depth--;
  1249. }
  1250. if (tok.getString() == "." && !dotOK) {
  1251. throw new ParserException("dot not expected", tok);
  1252. }
  1253. buf.append(tok.getString());
  1254. tokenSource.next();
  1255. dotOK = true;
  1256. }
  1257. return buf.toString();
  1258. }
  1259. public NamePattern parseNamePattern() {
  1260. StringBuffer buf = new StringBuffer();
  1261. IToken previous = null;
  1262. IToken tok;
  1263. int startPos = tokenSource.peek().getStart();
  1264. while (true) {
  1265. tok = tokenSource.peek();
  1266. if (previous != null) {
  1267. if (!isAdjacent(previous, tok)) {
  1268. break;
  1269. }
  1270. }
  1271. if (tok.getString() == "*" || tok.isIdentifier()) {
  1272. buf.append(tok.getString());
  1273. } else if (tok.getLiteralKind() != null) {
  1274. // System.err.println("literal kind: " + tok.getString());
  1275. String s = tok.getString();
  1276. if (s.indexOf('.') != -1) {
  1277. break;
  1278. }
  1279. buf.append(s); // ??? so-so
  1280. } else {
  1281. break;
  1282. }
  1283. previous = tokenSource.next();
  1284. // XXX need to handle floats and other fun stuff
  1285. }
  1286. int endPos = tokenSource.peek(-1).getEnd();
  1287. if (buf.length() == 0) {
  1288. throw new ParserException("name pattern", tok);
  1289. }
  1290. checkLegalName(buf.toString(), previous);
  1291. NamePattern ret = new NamePattern(buf.toString());
  1292. ret.setLocation(sourceContext, startPos, endPos);
  1293. return ret;
  1294. }
  1295. private void checkLegalName(String s, IToken tok) {
  1296. char ch = s.charAt(0);
  1297. if (!(ch == '*' || Character.isJavaIdentifierStart(ch))) {
  1298. throw new ParserException("illegal identifier start (" + ch + ")", tok);
  1299. }
  1300. for (int i = 1, len = s.length(); i < len; i++) {
  1301. ch = s.charAt(i);
  1302. if (!(ch == '*' || Character.isJavaIdentifierPart(ch))) {
  1303. throw new ParserException("illegal identifier character (" + ch + ")", tok);
  1304. }
  1305. }
  1306. }
  1307. private boolean isAdjacent(IToken first, IToken second) {
  1308. return first.getEnd() == second.getStart() - 1;
  1309. }
  1310. public ModifiersPattern parseModifiersPattern() {
  1311. int requiredFlags = 0;
  1312. int forbiddenFlags = 0;
  1313. int start;
  1314. while (true) {
  1315. start = tokenSource.getIndex();
  1316. boolean isForbidden = false;
  1317. isForbidden = maybeEat("!");
  1318. IToken t = tokenSource.next();
  1319. int flag = ModifiersPattern.getModifierFlag(t.getString());
  1320. if (flag == -1) {
  1321. break;
  1322. }
  1323. if (isForbidden) {
  1324. forbiddenFlags |= flag;
  1325. } else {
  1326. requiredFlags |= flag;
  1327. }
  1328. }
  1329. tokenSource.setIndex(start);
  1330. if (requiredFlags == 0 && forbiddenFlags == 0) {
  1331. return ModifiersPattern.ANY;
  1332. } else {
  1333. return new ModifiersPattern(requiredFlags, forbiddenFlags);
  1334. }
  1335. }
  1336. public TypePatternList parseArgumentsPattern(boolean parameterAnnotationsPossible) {
  1337. List<TypePattern> patterns = new ArrayList<TypePattern>();
  1338. eat("(");
  1339. // ()
  1340. if (maybeEat(")")) {
  1341. return new TypePatternList();
  1342. }
  1343. do {
  1344. if (maybeEat(".")) { // ..
  1345. eat(".");
  1346. patterns.add(TypePattern.ELLIPSIS);
  1347. } else {
  1348. patterns.add(parseTypePattern(false, parameterAnnotationsPossible));
  1349. }
  1350. } while (maybeEat(","));
  1351. eat(")");
  1352. return new TypePatternList(patterns);
  1353. }
  1354. public AnnotationPatternList parseArgumentsAnnotationPattern() {
  1355. List<AnnotationTypePattern> patterns = new ArrayList<AnnotationTypePattern>();
  1356. eat("(");
  1357. if (maybeEat(")")) {
  1358. return new AnnotationPatternList();
  1359. }
  1360. do {
  1361. if (maybeEat(".")) {
  1362. eat(".");
  1363. patterns.add(AnnotationTypePattern.ELLIPSIS);
  1364. } else if (maybeEat("*")) {
  1365. patterns.add(AnnotationTypePattern.ANY);
  1366. } else {
  1367. patterns.add(parseAnnotationNameOrVarTypePattern());
  1368. }
  1369. } while (maybeEat(","));
  1370. eat(")");
  1371. return new AnnotationPatternList(patterns);
  1372. }
  1373. public ThrowsPattern parseOptionalThrowsPattern() {
  1374. IToken t = tokenSource.peek();
  1375. if (t.isIdentifier() && t.getString().equals("throws")) {
  1376. tokenSource.next();
  1377. List<TypePattern> required = new ArrayList<TypePattern>();
  1378. List<TypePattern> forbidden = new ArrayList<TypePattern>();
  1379. do {
  1380. boolean isForbidden = maybeEat("!");
  1381. // ???might want an error for a second ! without a paren
  1382. TypePattern p = parseTypePattern();
  1383. if (isForbidden) {
  1384. forbidden.add(p);
  1385. } else {
  1386. required.add(p);
  1387. }
  1388. } while (maybeEat(","));
  1389. return new ThrowsPattern(new TypePatternList(required), new TypePatternList(forbidden));
  1390. }
  1391. return ThrowsPattern.ANY;
  1392. }
  1393. public SignaturePattern parseMethodOrConstructorSignaturePattern() {
  1394. int startPos = tokenSource.peek().getStart();
  1395. AnnotationTypePattern annotationPattern = maybeParseAnnotationPattern();
  1396. ModifiersPattern modifiers = parseModifiersPattern();
  1397. TypePattern returnType = parseTypePattern(false, false);
  1398. TypePattern declaringType;
  1399. NamePattern name = null;
  1400. MemberKind kind;
  1401. // here we can check for 'new'
  1402. if (maybeEatNew(returnType)) {
  1403. kind = Member.CONSTRUCTOR;
  1404. if (returnType.toString().length() == 0) {
  1405. declaringType = TypePattern.ANY;
  1406. } else {
  1407. declaringType = returnType;
  1408. }
  1409. returnType = TypePattern.ANY;
  1410. name = NamePattern.ANY;
  1411. } else {
  1412. kind = Member.METHOD;
  1413. IToken nameToken = tokenSource.peek();
  1414. declaringType = parseTypePattern(false, false);
  1415. if (maybeEat(".")) {
  1416. nameToken = tokenSource.peek();
  1417. name = parseNamePattern();
  1418. } else {
  1419. name = tryToExtractName(declaringType);
  1420. if (declaringType.toString().equals("")) {
  1421. declaringType = TypePattern.ANY;
  1422. }
  1423. }
  1424. if (name == null) {
  1425. throw new ParserException("name pattern", tokenSource.peek());
  1426. }
  1427. String simpleName = name.maybeGetSimpleName();
  1428. // XXX should add check for any Java keywords
  1429. if (simpleName != null && simpleName.equals("new")) {
  1430. throw new ParserException("method name (not constructor)", nameToken);
  1431. }
  1432. }
  1433. TypePatternList parameterTypes = parseArgumentsPattern(true);
  1434. ThrowsPattern throwsPattern = parseOptionalThrowsPattern();
  1435. SignaturePattern ret = new SignaturePattern(kind, modifiers, returnType, declaringType, name, parameterTypes,
  1436. throwsPattern, annotationPattern);
  1437. int endPos = tokenSource.peek(-1).getEnd();
  1438. ret.setLocation(sourceContext, startPos, endPos);
  1439. return ret;
  1440. }
  1441. private boolean maybeEatNew(TypePattern returnType) {
  1442. if (returnType instanceof WildTypePattern) {
  1443. WildTypePattern p = (WildTypePattern) returnType;
  1444. if (p.maybeExtractName("new")) {
  1445. return true;
  1446. }
  1447. }
  1448. int start = tokenSource.getIndex();
  1449. if (maybeEat(".")) {
  1450. String id = maybeEatIdentifier();
  1451. if (id != null && id.equals("new")) {
  1452. return true;
  1453. }
  1454. tokenSource.setIndex(start);
  1455. }
  1456. return false;
  1457. }
  1458. public ISignaturePattern parseMaybeParenthesizedFieldSignaturePattern() {
  1459. boolean negated = tokenSource.peek().getString().equals("!") && tokenSource.peek(1).getString().equals("(");
  1460. if (negated) {
  1461. eat("!");
  1462. }
  1463. ISignaturePattern result = null;
  1464. if (maybeEat("(")) {
  1465. result = parseCompoundFieldSignaturePattern();
  1466. eat(")", "missing ')' - unbalanced parentheses around field signature pattern in declare @field");
  1467. if (negated) {
  1468. result = new NotSignaturePattern(result);
  1469. }
  1470. } else {
  1471. result = parseFieldSignaturePattern();
  1472. }
  1473. return result;
  1474. }
  1475. public ISignaturePattern parseMaybeParenthesizedMethodOrConstructorSignaturePattern(boolean isMethod) {
  1476. boolean negated = tokenSource.peek().getString().equals("!") && tokenSource.peek(1).getString().equals("(");
  1477. if (negated) {
  1478. eat("!");
  1479. }
  1480. ISignaturePattern result = null;
  1481. if (maybeEat("(")) {
  1482. result = parseCompoundMethodOrConstructorSignaturePattern(isMethod);
  1483. eat(")", "missing ')' - unbalanced parentheses around method/ctor signature pattern in declare annotation");
  1484. if (negated) {
  1485. result = new NotSignaturePattern(result);
  1486. }
  1487. } else {
  1488. SignaturePattern sp = parseMethodOrConstructorSignaturePattern();
  1489. boolean isConstructorPattern = (sp.getKind() == Member.CONSTRUCTOR);
  1490. if (isMethod && isConstructorPattern) {
  1491. throw new ParserException("method signature pattern", tokenSource.peek(-1));
  1492. }
  1493. if (!isMethod && !isConstructorPattern) {
  1494. throw new ParserException("constructor signature pattern", tokenSource.peek(-1));
  1495. }
  1496. result = sp;
  1497. }
  1498. return result;
  1499. }
  1500. public SignaturePattern parseFieldSignaturePattern() {
  1501. int startPos = tokenSource.peek().getStart();
  1502. // TypePatternList followMe = TypePatternList.ANY;
  1503. AnnotationTypePattern annotationPattern = maybeParseAnnotationPattern();
  1504. ModifiersPattern modifiers = parseModifiersPattern();
  1505. TypePattern returnType = parseTypePattern();
  1506. TypePattern declaringType = parseTypePattern();
  1507. NamePattern name;
  1508. // System.err.println("parsed field: " + declaringType.toString());
  1509. if (maybeEat(".")) {
  1510. name = parseNamePattern();
  1511. } else {
  1512. name = tryToExtractName(declaringType);
  1513. if (name == null) {
  1514. throw new ParserException("name pattern", tokenSource.peek());
  1515. }
  1516. if (declaringType.toString().equals("")) {
  1517. declaringType = TypePattern.ANY;
  1518. }
  1519. }
  1520. SignaturePattern ret = new SignaturePattern(Member.FIELD, modifiers, returnType, declaringType, name, TypePatternList.ANY,
  1521. ThrowsPattern.ANY, annotationPattern);
  1522. int endPos = tokenSource.peek(-1).getEnd();
  1523. ret.setLocation(sourceContext, startPos, endPos);
  1524. return ret;
  1525. }
  1526. private NamePattern tryToExtractName(TypePattern nextType) {
  1527. if (nextType == TypePattern.ANY) {
  1528. return NamePattern.ANY;
  1529. } else if (nextType instanceof WildTypePattern) {
  1530. WildTypePattern p = (WildTypePattern) nextType;
  1531. return p.extractName();
  1532. } else {
  1533. return null;
  1534. }
  1535. }
  1536. /**
  1537. * Parse type variable declarations for a generic method or at the start of a signature pointcut to identify type variable names
  1538. * in a generic type.
  1539. *
  1540. * @param includeParameterizedTypes
  1541. * @return
  1542. */
  1543. public TypeVariablePatternList maybeParseTypeVariableList() {
  1544. if (!maybeEat("<")) {
  1545. return null;
  1546. }
  1547. List<TypeVariablePattern> typeVars = new ArrayList<TypeVariablePattern>();
  1548. TypeVariablePattern t = parseTypeVariable();
  1549. typeVars.add(t);
  1550. while (maybeEat(",")) {
  1551. TypeVariablePattern nextT = parseTypeVariable();
  1552. typeVars.add(nextT);
  1553. }
  1554. eat(">");
  1555. TypeVariablePattern[] tvs = new TypeVariablePattern[typeVars.size()];
  1556. typeVars.toArray(tvs);
  1557. return new TypeVariablePatternList(tvs);
  1558. }
  1559. // of the form execution<T,S,V> - allows identifiers only
  1560. public String[] maybeParseSimpleTypeVariableList() {
  1561. if (!maybeEat("<")) {
  1562. return null;
  1563. }
  1564. List<String> typeVarNames = new ArrayList<String>();
  1565. do {
  1566. typeVarNames.add(parseIdentifier());
  1567. } while (maybeEat(","));
  1568. eat(">", "',' or '>'");
  1569. String[] tvs = new String[typeVarNames.size()];
  1570. typeVarNames.toArray(tvs);
  1571. return tvs;
  1572. }
  1573. public TypePatternList maybeParseTypeParameterList() {
  1574. if (!maybeEat("<")) {
  1575. return null;
  1576. }
  1577. List<TypePattern> typePats = new ArrayList<TypePattern>();
  1578. do {
  1579. TypePattern tp = parseTypePattern(true, false);
  1580. typePats.add(tp);
  1581. } while (maybeEat(","));
  1582. eat(">");
  1583. TypePattern[] tps = new TypePattern[typePats.size()];
  1584. typePats.toArray(tps);
  1585. return new TypePatternList(tps);
  1586. }
  1587. public TypeVariablePattern parseTypeVariable() {
  1588. TypePattern upperBound = null;
  1589. TypePattern[] additionalInterfaceBounds = null;
  1590. TypePattern lowerBound = null;
  1591. String typeVariableName = parseIdentifier();
  1592. if (maybeEatIdentifier("extends")) {
  1593. upperBound = parseTypePattern();
  1594. additionalInterfaceBounds = maybeParseAdditionalInterfaceBounds();
  1595. } else if (maybeEatIdentifier("super")) {
  1596. lowerBound = parseTypePattern();
  1597. }
  1598. return new TypeVariablePattern(typeVariableName, upperBound, additionalInterfaceBounds, lowerBound);
  1599. }
  1600. private TypePattern[] maybeParseAdditionalInterfaceBounds() {
  1601. List<TypePattern> boundsList = new ArrayList<TypePattern>();
  1602. while (maybeEat("&")) {
  1603. TypePattern tp = parseTypePattern();
  1604. boundsList.add(tp);
  1605. }
  1606. if (boundsList.size() == 0) {
  1607. return null;
  1608. }
  1609. TypePattern[] ret = new TypePattern[boundsList.size()];
  1610. boundsList.toArray(ret);
  1611. return ret;
  1612. }
  1613. public String parsePossibleStringSequence(boolean shouldEnd) {
  1614. StringBuffer result = new StringBuffer();
  1615. IToken token = tokenSource.next();
  1616. if (token.getLiteralKind() == null) {
  1617. throw new ParserException("string", token);
  1618. }
  1619. while (token.getLiteralKind().equals("string")) {
  1620. result.append(token.getString());
  1621. boolean plus = maybeEat("+");
  1622. if (!plus) {
  1623. break;
  1624. }
  1625. token = tokenSource.next();
  1626. if (token.getLiteralKind() == null) {
  1627. throw new ParserException("string", token);
  1628. }
  1629. }
  1630. eatIdentifier(";");
  1631. IToken t = tokenSource.next();
  1632. if (shouldEnd && t != IToken.EOF) {
  1633. throw new ParserException("<string>;", token);
  1634. }
  1635. // bug 125027: since we've eaten the ";" we need to set the index
  1636. // to be one less otherwise the end position isn't set correctly.
  1637. int currentIndex = tokenSource.getIndex();
  1638. tokenSource.setIndex(currentIndex - 1);
  1639. return result.toString();
  1640. }
  1641. public String parseStringLiteral() {
  1642. IToken token = tokenSource.next();
  1643. String literalKind = token.getLiteralKind();
  1644. if (literalKind == "string") {
  1645. return token.getString();
  1646. }
  1647. throw new ParserException("string", token);
  1648. }
  1649. public String parseIdentifier() {
  1650. IToken token = tokenSource.next();
  1651. if (token.isIdentifier()) {
  1652. return token.getString();
  1653. }
  1654. throw new ParserException("identifier", token);
  1655. }
  1656. public void eatIdentifier(String expectedValue) {
  1657. IToken next = tokenSource.next();
  1658. if (!next.getString().equals(expectedValue)) {
  1659. throw new ParserException(expectedValue, next);
  1660. }
  1661. }
  1662. public boolean maybeEatIdentifier(String expectedValue) {
  1663. IToken next = tokenSource.peek();
  1664. if (next.getString().equals(expectedValue)) {
  1665. tokenSource.next();
  1666. return true;
  1667. } else {
  1668. return false;
  1669. }
  1670. }
  1671. public void eat(String expectedValue) {
  1672. eat(expectedValue, expectedValue);
  1673. }
  1674. private void eat(String expectedValue, String expectedMessage) {
  1675. IToken next = nextToken();
  1676. if (next.getString() != expectedValue) {
  1677. if (expectedValue.equals(">") && next.getString().startsWith(">")) {
  1678. // handle problem of >> and >>> being lexed as single tokens
  1679. pendingRightArrows = BasicToken.makeLiteral(next.getString().substring(1).intern(), "string", next.getStart() + 1,
  1680. next.getEnd());
  1681. return;
  1682. }
  1683. throw new ParserException(expectedMessage, next);
  1684. }
  1685. }
  1686. private IToken pendingRightArrows;
  1687. private IToken nextToken() {
  1688. if (pendingRightArrows != null) {
  1689. IToken ret = pendingRightArrows;
  1690. pendingRightArrows = null;
  1691. return ret;
  1692. } else {
  1693. return tokenSource.next();
  1694. }
  1695. }
  1696. public boolean maybeEatAdjacent(String token) {
  1697. IToken next = tokenSource.peek();
  1698. if (next.getString() == token) {
  1699. if (isAdjacent(tokenSource.peek(-1), next)) {
  1700. tokenSource.next();
  1701. return true;
  1702. }
  1703. }
  1704. return false;
  1705. }
  1706. public boolean maybeEat(String token) {
  1707. IToken next = tokenSource.peek();
  1708. if (next.getString() == token) {
  1709. tokenSource.next();
  1710. return true;
  1711. } else {
  1712. return false;
  1713. }
  1714. }
  1715. public String maybeEatIdentifier() {
  1716. IToken next = tokenSource.peek();
  1717. if (next.isIdentifier()) {
  1718. tokenSource.next();
  1719. return next.getString();
  1720. } else {
  1721. return null;
  1722. }
  1723. }
  1724. public boolean peek(String token) {
  1725. IToken next = tokenSource.peek();
  1726. return next.getString() == token;
  1727. }
  1728. public void checkEof() {
  1729. IToken last = tokenSource.next();
  1730. if (last != IToken.EOF) {
  1731. throw new ParserException("unexpected pointcut element: " + last.toString(), last);
  1732. }
  1733. }
  1734. public PatternParser(String data) {
  1735. this(BasicTokenSource.makeTokenSource(data, null));
  1736. }
  1737. public PatternParser(String data, ISourceContext context) {
  1738. this(BasicTokenSource.makeTokenSource(data, context));
  1739. }
  1740. }