1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900 |
- /* *******************************************************************
- * Copyright (c) 2002,2010
- * All rights reserved.
- * This program and the accompanying materials are made available
- * under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * PARC initial implementation
- * Adrian Colyer, IBM
- * Andy Clement, IBM, SpringSource
- * ******************************************************************/
-
- package org.aspectj.weaver.patterns;
-
- import java.util.ArrayList;
- import java.util.Collections;
- import java.util.HashMap;
- import java.util.List;
- import java.util.Map;
- import java.util.Set;
-
- import org.aspectj.weaver.ISourceContext;
- import org.aspectj.weaver.Member;
- import org.aspectj.weaver.MemberKind;
- import org.aspectj.weaver.Shadow;
- import org.aspectj.weaver.UnresolvedType;
- import org.aspectj.weaver.World;
- import org.aspectj.weaver.internal.tools.PointcutDesignatorHandlerBasedPointcut;
- import org.aspectj.weaver.tools.ContextBasedMatcher;
- import org.aspectj.weaver.tools.PointcutDesignatorHandler;
-
- /**
- * @author PARC
- * @author Adrian Colyer
- * @author Andy Clement
- */
- // XXX doesn't handle errors for extra tokens very well (sometimes ignores)
- public class PatternParser {
-
- private ITokenSource tokenSource;
- private ISourceContext sourceContext;
-
- /** not thread-safe, but this class is not intended to be... */
- private boolean allowHasTypePatterns = false;
-
- /** extension handlers used in weaver tools API only */
- private Set<PointcutDesignatorHandler> pointcutDesignatorHandlers = Collections.emptySet();
- private World world;
-
- /**
- * Constructor for PatternParser.
- */
- public PatternParser(ITokenSource tokenSource) {
- super();
- this.tokenSource = tokenSource;
- this.sourceContext = tokenSource.getSourceContext();
- }
-
- /** only used by weaver tools API */
- public void setPointcutDesignatorHandlers(Set<PointcutDesignatorHandler> handlers, World world) {
- this.pointcutDesignatorHandlers = handlers;
- this.world = world;
- }
-
- public PerClause maybeParsePerClause() {
- IToken tok = tokenSource.peek();
- if (tok == IToken.EOF) {
- return null;
- }
- if (tok.isIdentifier()) {
- String name = tok.getString();
- if (name.equals("issingleton")) {
- return parsePerSingleton();
- } else if (name.equals("perthis")) {
- return parsePerObject(true);
- } else if (name.equals("pertarget")) {
- return parsePerObject(false);
- } else if (name.equals("percflow")) {
- return parsePerCflow(false);
- } else if (name.equals("percflowbelow")) {
- return parsePerCflow(true);
- } else if (name.equals("pertypewithin")) { // PTWIMPL Parse the pertypewithin clause
- return parsePerTypeWithin();
- } else {
- return null;
- }
- }
- return null;
- }
-
- private PerClause parsePerCflow(boolean isBelow) {
- parseIdentifier();
- eat("(");
- Pointcut entry = parsePointcut();
- eat(")");
- return new PerCflow(entry, isBelow);
- }
-
- private PerClause parsePerObject(boolean isThis) {
- parseIdentifier();
- eat("(");
- Pointcut entry = parsePointcut();
- eat(")");
- return new PerObject(entry, isThis);
- }
-
- private PerClause parsePerTypeWithin() {
- parseIdentifier();
- eat("(");
- TypePattern withinTypePattern = parseTypePattern();
- eat(")");
- return new PerTypeWithin(withinTypePattern);
- }
-
- private PerClause parsePerSingleton() {
- parseIdentifier();
- eat("(");
- eat(")");
- return new PerSingleton();
- }
-
- public Declare parseDeclare() {
- int startPos = tokenSource.peek().getStart();
-
- eatIdentifier("declare");
- String kind = parseIdentifier();
- Declare ret;
- if (kind.equals("error")) {
- eat(":");
- ret = parseErrorOrWarning(true);
- } else if (kind.equals("warning")) {
- eat(":");
- ret = parseErrorOrWarning(false);
- } else if (kind.equals("precedence")) {
- eat(":");
- ret = parseDominates();
- } else if (kind.equals("dominates")) {
- throw new ParserException("name changed to declare precedence", tokenSource.peek(-2));
- } else if (kind.equals("parents")) {
- ret = parseParents();
- } else if (kind.equals("soft")) {
- eat(":");
- ret = parseSoft();
- } else {
- throw new ParserException(
- "expected one of error, warning, parents, soft, precedence, @type, @method, @constructor, @field",
- tokenSource.peek(-1));
- }
- int endPos = tokenSource.peek(-1).getEnd();
- ret.setLocation(sourceContext, startPos, endPos);
- return ret;
- }
-
- public Declare parseDeclareAnnotation() {
- int startPos = tokenSource.peek().getStart();
-
- eatIdentifier("declare");
- eat("@");
- String kind = parseIdentifier();
- eat(":");
- Declare ret;
- if (kind.equals("type")) {
- ret = parseDeclareAtType();
- } else if (kind.equals("method")) {
- ret = parseDeclareAtMethod(true);
- } else if (kind.equals("field")) {
- ret = parseDeclareAtField();
- } else if (kind.equals("constructor")) {
- ret = parseDeclareAtMethod(false);
- } else {
- throw new ParserException("one of type, method, field, constructor", tokenSource.peek(-1));
- }
- eat(";");
- int endPos = tokenSource.peek(-1).getEnd();
- ret.setLocation(sourceContext, startPos, endPos);
- return ret;
-
- }
-
- public DeclareAnnotation parseDeclareAtType() {
- allowHasTypePatterns = true;
- TypePattern p = parseTypePattern();
- allowHasTypePatterns = false;
- return new DeclareAnnotation(DeclareAnnotation.AT_TYPE, p);
- }
-
- public DeclareAnnotation parseDeclareAtMethod(boolean isMethod) {
- ISignaturePattern sp = parseCompoundMethodOrConstructorSignaturePattern(isMethod);// parseMethodOrConstructorSignaturePattern();
-
- if (!isMethod) {
- return new DeclareAnnotation(DeclareAnnotation.AT_CONSTRUCTOR, sp);
- } else {
- return new DeclareAnnotation(DeclareAnnotation.AT_METHOD, sp);
- }
- }
-
- public DeclareAnnotation parseDeclareAtField() {
- ISignaturePattern compoundFieldSignaturePattern = parseCompoundFieldSignaturePattern();
- DeclareAnnotation da = new DeclareAnnotation(DeclareAnnotation.AT_FIELD, compoundFieldSignaturePattern);
- return da;
- }
-
- public ISignaturePattern parseCompoundFieldSignaturePattern() {
- int index = tokenSource.getIndex();
- try {
- ISignaturePattern atomicFieldSignaturePattern = parseMaybeParenthesizedFieldSignaturePattern();
-
- while (isEitherAndOrOr()) {
- if (maybeEat("&&")) {
- atomicFieldSignaturePattern = new AndSignaturePattern(atomicFieldSignaturePattern,
- parseMaybeParenthesizedFieldSignaturePattern());
- }
- if (maybeEat("||")) {
- atomicFieldSignaturePattern = new OrSignaturePattern(atomicFieldSignaturePattern,
- parseMaybeParenthesizedFieldSignaturePattern());
- }
- }
- return atomicFieldSignaturePattern;
- } catch (ParserException e) {
- // fallback in the case of a regular single field signature pattern that just happened to start with '('
- int nowAt = tokenSource.getIndex();
- tokenSource.setIndex(index);
- try {
- ISignaturePattern fsp = parseFieldSignaturePattern();
- return fsp;
- } catch (Exception e2) {
- tokenSource.setIndex(nowAt);
- // throw the original
- throw e;
- }
- }
- }
-
- private boolean isEitherAndOrOr() {
- String tokenstring = tokenSource.peek().getString();
- return tokenstring.equals("&&") || tokenstring.equals("||");
- }
-
- public ISignaturePattern parseCompoundMethodOrConstructorSignaturePattern(boolean isMethod) {
- ISignaturePattern atomicMethodCtorSignaturePattern = parseMaybeParenthesizedMethodOrConstructorSignaturePattern(isMethod);
-
- while (isEitherAndOrOr()) {
- if (maybeEat("&&")) {
- atomicMethodCtorSignaturePattern = new AndSignaturePattern(atomicMethodCtorSignaturePattern,
- parseMaybeParenthesizedMethodOrConstructorSignaturePattern(isMethod));
- }
- if (maybeEat("||")) {
- atomicMethodCtorSignaturePattern = new OrSignaturePattern(atomicMethodCtorSignaturePattern,
- parseMaybeParenthesizedMethodOrConstructorSignaturePattern(isMethod));
- }
- }
- return atomicMethodCtorSignaturePattern;
- }
-
- public DeclarePrecedence parseDominates() {
- List<TypePattern> l = new ArrayList<TypePattern>();
- do {
- l.add(parseTypePattern());
- } while (maybeEat(","));
-
- return new DeclarePrecedence(l);
- }
-
- private Declare parseParents() {
- /*
- * simplified design requires use of raw types for declare parents, no generic spec. allowed String[] typeParameters =
- * maybeParseSimpleTypeVariableList();
- */
- eat(":");
- allowHasTypePatterns = true;
- TypePattern p = parseTypePattern(false, false);
- allowHasTypePatterns = false;
- IToken t = tokenSource.next();
- if (!(t.getString().equals("extends") || t.getString().equals("implements"))) {
- throw new ParserException("extends or implements", t);
- }
- boolean isExtends = t.getString().equals("extends");
-
- List<TypePattern> l = new ArrayList<TypePattern>();
- do {
- l.add(parseTypePattern());
- } while (maybeEat(","));
-
- // XXX somewhere in the chain we need to enforce that we have only ExactTypePatterns
-
- DeclareParents decp = new DeclareParents(p, l, isExtends);
- return decp;
- }
-
- private Declare parseSoft() {
- TypePattern p = parseTypePattern();
- eat(":");
- Pointcut pointcut = parsePointcut();
- return new DeclareSoft(p, pointcut);
- }
-
- /**
- * Attempt to parse a pointcut, if that fails then try again for a type pattern.
- *
- * @param isError true if it is declare error rather than declare warning
- * @return the new declare
- */
- private Declare parseErrorOrWarning(boolean isError) {
- Pointcut pointcut = null;
- int index = tokenSource.getIndex();
- try {
- pointcut = parsePointcut();
- } catch (ParserException pe) {
- try {
- tokenSource.setIndex(index);
- boolean oldValue = allowHasTypePatterns;
- TypePattern typePattern = null;
- try {
- allowHasTypePatterns = true;
- typePattern = parseTypePattern();
- } finally {
- allowHasTypePatterns = oldValue;
- }
- eat(":");
- String message = parsePossibleStringSequence(true);
- return new DeclareTypeErrorOrWarning(isError, typePattern, message);
- } catch (ParserException pe2) {
- // deliberately throw the original problem
- throw pe;
- }
- }
- eat(":");
- String message = parsePossibleStringSequence(true);
- return new DeclareErrorOrWarning(isError, pointcut, message);
- }
-
- public Pointcut parsePointcut() {
- Pointcut p = parseAtomicPointcut();
- if (maybeEat("&&")) {
- p = new AndPointcut(p, parseNotOrPointcut());
- }
-
- if (maybeEat("||")) {
- p = new OrPointcut(p, parsePointcut());
- }
-
- return p;
- }
-
- private Pointcut parseNotOrPointcut() {
- Pointcut p = parseAtomicPointcut();
- if (maybeEat("&&")) {
- p = new AndPointcut(p, parseNotOrPointcut());
- }
- return p;
- }
-
- private Pointcut parseAtomicPointcut() {
- if (maybeEat("!")) {
- int startPos = tokenSource.peek(-1).getStart();
- Pointcut p = new NotPointcut(parseAtomicPointcut(), startPos);
- return p;
- }
- if (maybeEat("(")) {
- Pointcut p = parsePointcut();
- eat(")");
- return p;
- }
- if (maybeEat("@")) {
- int startPos = tokenSource.peek().getStart();
- Pointcut p = parseAnnotationPointcut();
- int endPos = tokenSource.peek(-1).getEnd();
- p.setLocation(sourceContext, startPos, endPos);
- return p;
- }
- int startPos = tokenSource.peek().getStart();
- Pointcut p = parseSinglePointcut();
- int endPos = tokenSource.peek(-1).getEnd();
- p.setLocation(sourceContext, startPos, endPos);
- return p;
- }
-
- public Pointcut parseSinglePointcut() {
- int start = tokenSource.getIndex();
- IToken t = tokenSource.peek();
- Pointcut p = t.maybeGetParsedPointcut();
- if (p != null) {
- tokenSource.next();
- return p;
- }
-
- String kind = parseIdentifier();
- // IToken possibleTypeVariableToken = tokenSource.peek();
- // String[] typeVariables = maybeParseSimpleTypeVariableList();
- if (kind.equals("execution") || kind.equals("call") || kind.equals("get") || kind.equals("set")) {
- p = parseKindedPointcut(kind);
- } else if (kind.equals("args")) {
- p = parseArgsPointcut();
- } else if (kind.equals("this")) {
- p = parseThisOrTargetPointcut(kind);
- } else if (kind.equals("target")) {
- p = parseThisOrTargetPointcut(kind);
- } else if (kind.equals("within")) {
- p = parseWithinPointcut();
- } else if (kind.equals("withincode")) {
- p = parseWithinCodePointcut();
- } else if (kind.equals("cflow")) {
- p = parseCflowPointcut(false);
- } else if (kind.equals("cflowbelow")) {
- p = parseCflowPointcut(true);
- } else if (kind.equals("adviceexecution")) {
- eat("(");
- eat(")");
- p = new KindedPointcut(Shadow.AdviceExecution, new SignaturePattern(Member.ADVICE, ModifiersPattern.ANY,
- TypePattern.ANY, TypePattern.ANY, NamePattern.ANY, TypePatternList.ANY, ThrowsPattern.ANY,
- AnnotationTypePattern.ANY));
- } else if (kind.equals("handler")) {
- eat("(");
- TypePattern typePat = parseTypePattern(false, false);
- eat(")");
- p = new HandlerPointcut(typePat);
- } else if (kind.equals("lock") || kind.equals("unlock")) {
- p = parseMonitorPointcut(kind);
- } else if (kind.equals("initialization")) {
- eat("(");
- SignaturePattern sig = parseConstructorSignaturePattern();
- eat(")");
- p = new KindedPointcut(Shadow.Initialization, sig);
- } else if (kind.equals("staticinitialization")) {
- eat("(");
- TypePattern typePat = parseTypePattern(false, false);
- eat(")");
- p = new KindedPointcut(Shadow.StaticInitialization, new SignaturePattern(Member.STATIC_INITIALIZATION,
- ModifiersPattern.ANY, TypePattern.ANY, typePat, NamePattern.ANY, TypePatternList.EMPTY, ThrowsPattern.ANY,
- AnnotationTypePattern.ANY));
- } else if (kind.equals("preinitialization")) {
- eat("(");
- SignaturePattern sig = parseConstructorSignaturePattern();
- eat(")");
- p = new KindedPointcut(Shadow.PreInitialization, sig);
- } else if (kind.equals("if")) {
- // - annotation style only allows if(), if(true) or if(false)
- // - if() means the body of the annotated method represents the if expression
- // - anything else is an error because code cannot be put into the if()
- // - code style will already have been processed and the call to maybeGetParsedPointcut()
- // at the top of this method will have succeeded.
- eat("(");
- if (maybeEatIdentifier("true")) {
- eat(")");
- p = new IfPointcut.IfTruePointcut();
- } else if (maybeEatIdentifier("false")) {
- eat(")");
- p = new IfPointcut.IfFalsePointcut();
- } else {
- if (!maybeEat(")")) {
- throw new ParserException(
- "in annotation style, if(...) pointcuts cannot contain code. Use if() and put the code in the annotated method",
- t);
- }
- // TODO - Alex has some token stuff going on here to get a readable name in place of ""...
- p = new IfPointcut("");
- }
- } else {
- boolean matchedByExtensionDesignator = false;
- // see if a registered handler wants to parse it, otherwise
- // treat as a reference pointcut
- for (PointcutDesignatorHandler pcd : pointcutDesignatorHandlers) {
- if (pcd.getDesignatorName().equals(kind)) {
- p = parseDesignatorPointcut(pcd);
- matchedByExtensionDesignator = true;
- }
-
- }
- if (!matchedByExtensionDesignator) {
- tokenSource.setIndex(start);
- p = parseReferencePointcut();
- }
- }
- return p;
- }
-
- private void assertNoTypeVariables(String[] tvs, String errorMessage, IToken token) {
- if (tvs != null) {
- throw new ParserException(errorMessage, token);
- }
- }
-
- public Pointcut parseAnnotationPointcut() {
- int start = tokenSource.getIndex();
- IToken t = tokenSource.peek();
- String kind = parseIdentifier();
- IToken possibleTypeVariableToken = tokenSource.peek();
- String[] typeVariables = maybeParseSimpleTypeVariableList();
- if (typeVariables != null) {
- String message = "(";
- assertNoTypeVariables(typeVariables, message, possibleTypeVariableToken);
- }
- tokenSource.setIndex(start);
- if (kind.equals("annotation")) {
- return parseAtAnnotationPointcut();
- } else if (kind.equals("args")) {
- return parseArgsAnnotationPointcut();
- } else if (kind.equals("this") || kind.equals("target")) {
- return parseThisOrTargetAnnotationPointcut();
- } else if (kind.equals("within")) {
- return parseWithinAnnotationPointcut();
- } else if (kind.equals("withincode")) {
- return parseWithinCodeAnnotationPointcut();
- }
- throw new ParserException("pointcut name", t);
- }
-
- private Pointcut parseAtAnnotationPointcut() {
- parseIdentifier();
- eat("(");
- if (maybeEat(")")) {
- throw new ParserException("@AnnotationName or parameter", tokenSource.peek());
- }
- ExactAnnotationTypePattern type = parseAnnotationNameOrVarTypePattern();
- eat(")");
- return new AnnotationPointcut(type);
- }
-
- private SignaturePattern parseConstructorSignaturePattern() {
- SignaturePattern ret = parseMethodOrConstructorSignaturePattern();
- if (ret.getKind() == Member.CONSTRUCTOR) {
- return ret;
- }
-
- throw new ParserException("constructor pattern required, found method pattern", ret);
- }
-
- private Pointcut parseWithinCodePointcut() {
- // parseIdentifier();
- eat("(");
- SignaturePattern sig = parseMethodOrConstructorSignaturePattern();
- eat(")");
- return new WithincodePointcut(sig);
- }
-
- private Pointcut parseCflowPointcut(boolean isBelow) {
- // parseIdentifier();
- eat("(");
- Pointcut entry = parsePointcut();
- eat(")");
- return new CflowPointcut(entry, isBelow, null);
- }
-
- /**
- * Method parseWithinPointcut.
- *
- * @return Pointcut
- */
- private Pointcut parseWithinPointcut() {
- // parseIdentifier();
- eat("(");
- TypePattern type = parseTypePattern();
- eat(")");
- return new WithinPointcut(type);
- }
-
- /**
- * Method parseThisOrTargetPointcut.
- *
- * @return Pointcut
- */
- private Pointcut parseThisOrTargetPointcut(String kind) {
- boolean optional = false;
- if (maybeEat("?")) {
- optional = true;
- }
- eat("(");
- TypePattern type = parseTypePattern();
- eat(")");
- return new ThisOrTargetPointcut(kind.equals("this"), type,optional);
- }
-
- private Pointcut parseThisOrTargetAnnotationPointcut() {
- String kind = parseIdentifier();
- eat("(");
- if (maybeEat(")")) {
- throw new ParserException("expecting @AnnotationName or parameter, but found ')'", tokenSource.peek());
- }
- ExactAnnotationTypePattern type = parseAnnotationNameOrVarTypePattern();
- eat(")");
- return new ThisOrTargetAnnotationPointcut(kind.equals("this"), type);
- }
-
- private Pointcut parseWithinAnnotationPointcut() {
- /* String kind = */parseIdentifier();
- eat("(");
- if (maybeEat(")")) {
- throw new ParserException("expecting @AnnotationName or parameter, but found ')'", tokenSource.peek());
- }
- AnnotationTypePattern type = parseAnnotationNameOrVarTypePattern();
- eat(")");
- return new WithinAnnotationPointcut(type);
- }
-
- private Pointcut parseWithinCodeAnnotationPointcut() {
- /* String kind = */parseIdentifier();
- eat("(");
- if (maybeEat(")")) {
- throw new ParserException("expecting @AnnotationName or parameter, but found ')'", tokenSource.peek());
- }
- ExactAnnotationTypePattern type = parseAnnotationNameOrVarTypePattern();
- eat(")");
- return new WithinCodeAnnotationPointcut(type);
- }
-
- /**
- * Method parseArgsPointcut.
- *
- * @return Pointcut
- */
- private Pointcut parseArgsPointcut() {
- // parseIdentifier();
- TypePatternList arguments = parseArgumentsPattern(false);
- return new ArgsPointcut(arguments);
- }
-
- private Pointcut parseArgsAnnotationPointcut() {
- parseIdentifier();
- AnnotationPatternList arguments = parseArgumentsAnnotationPattern();
- return new ArgsAnnotationPointcut(arguments);
- }
-
- private Pointcut parseReferencePointcut() {
- TypePattern onType = parseTypePattern();
- NamePattern name = null;
- if (onType.typeParameters.size() > 0) {
- eat(".");
- name = parseNamePattern();
- } else {
- name = tryToExtractName(onType);
- }
- if (name == null) {
- throw new ParserException("name pattern", tokenSource.peek());
- }
- if (onType.toString().equals("")) {
- onType = null;
- }
-
- String simpleName = name.maybeGetSimpleName();
- if (simpleName == null) {
- throw new ParserException("(", tokenSource.peek(-1));
- }
-
- TypePatternList arguments = parseArgumentsPattern(false);
- return new ReferencePointcut(onType, simpleName, arguments);
- }
-
- private Pointcut parseDesignatorPointcut(PointcutDesignatorHandler pcdHandler) {
- eat("(");
- int parenCount = 1;
- StringBuffer pointcutBody = new StringBuffer();
- while (parenCount > 0) {
- if (maybeEat("(")) {
- parenCount++;
- pointcutBody.append("(");
- } else if (maybeEat(")")) {
- parenCount--;
- if (parenCount > 0) {
- pointcutBody.append(")");
- }
- } else {
- pointcutBody.append(nextToken().getString());
- }
- }
- ContextBasedMatcher pcExpr = pcdHandler.parse(pointcutBody.toString());
- return new PointcutDesignatorHandlerBasedPointcut(pcExpr, world);
- }
-
- public List<String> parseDottedIdentifier() {
- List<String> ret = new ArrayList<String>();
- ret.add(parseIdentifier());
- while (maybeEat(".")) {
- ret.add(parseIdentifier());
- }
- return ret;
- }
-
- private KindedPointcut parseKindedPointcut(String kind) {
- eat("(");
- SignaturePattern sig;
-
- Shadow.Kind shadowKind = null;
- if (kind.equals("execution")) {
- sig = parseMethodOrConstructorSignaturePattern();
- if (sig.getKind() == Member.METHOD) {
- shadowKind = Shadow.MethodExecution;
- } else if (sig.getKind() == Member.CONSTRUCTOR) {
- shadowKind = Shadow.ConstructorExecution;
- }
- } else if (kind.equals("call")) {
- sig = parseMethodOrConstructorSignaturePattern();
- if (sig.getKind() == Member.METHOD) {
- shadowKind = Shadow.MethodCall;
- } else if (sig.getKind() == Member.CONSTRUCTOR) {
- shadowKind = Shadow.ConstructorCall;
- }
- } else if (kind.equals("get")) {
- sig = parseFieldSignaturePattern();
- shadowKind = Shadow.FieldGet;
- } else if (kind.equals("set")) {
- sig = parseFieldSignaturePattern();
- shadowKind = Shadow.FieldSet;
- } else {
- throw new ParserException("bad kind: " + kind, tokenSource.peek());
- }
- eat(")");
- return new KindedPointcut(shadowKind, sig);
- }
-
- /** Covers the 'lock()' and 'unlock()' pointcuts */
- private KindedPointcut parseMonitorPointcut(String kind) {
- eat("(");
- // TypePattern type = TypePattern.ANY;
- eat(")");
-
- if (kind.equals("lock")) {
- return new KindedPointcut(Shadow.SynchronizationLock, new SignaturePattern(Member.MONITORENTER, ModifiersPattern.ANY,
- TypePattern.ANY, TypePattern.ANY,
- // type,
- NamePattern.ANY, TypePatternList.ANY, ThrowsPattern.ANY, AnnotationTypePattern.ANY));
- } else {
- return new KindedPointcut(Shadow.SynchronizationUnlock, new SignaturePattern(Member.MONITORENTER, ModifiersPattern.ANY,
- TypePattern.ANY, TypePattern.ANY,
- // type,
- NamePattern.ANY, TypePatternList.ANY, ThrowsPattern.ANY, AnnotationTypePattern.ANY));
- }
- }
-
- public TypePattern parseTypePattern() {
- return parseTypePattern(false, false);
- }
-
- public TypePattern parseTypePattern(boolean insideTypeParameters, boolean parameterAnnotationsPossible) {
- TypePattern p = parseAtomicTypePattern(insideTypeParameters, parameterAnnotationsPossible);
- if (maybeEat("&&")) {
- p = new AndTypePattern(p, parseNotOrTypePattern(insideTypeParameters, parameterAnnotationsPossible));
- }
-
- if (maybeEat("||")) {
- p = new OrTypePattern(p, parseTypePattern(insideTypeParameters, parameterAnnotationsPossible));
- }
- return p;
- }
-
- private TypePattern parseNotOrTypePattern(boolean insideTypeParameters, boolean parameterAnnotationsPossible) {
- TypePattern p = parseAtomicTypePattern(insideTypeParameters, parameterAnnotationsPossible);
- if (maybeEat("&&")) {
- p = new AndTypePattern(p, parseTypePattern(insideTypeParameters, parameterAnnotationsPossible));
- }
- return p;
- }
-
- // Need to differentiate in here between two kinds of annotation pattern - depending on where the ( is
-
- private TypePattern parseAtomicTypePattern(boolean insideTypeParameters, boolean parameterAnnotationsPossible) {
- AnnotationTypePattern ap = maybeParseAnnotationPattern(); // might be parameter annotation pattern or type annotation
- // pattern
- if (maybeEat("!")) {
- // int startPos = tokenSource.peek(-1).getStart();
- // ??? we lose source location for true start of !type
-
- // An annotation, if processed, is outside of the Not - so here we have to build
- // an And pattern containing the annotation and the not as left and right children
- // *unless* the annotation pattern was just 'Any' then we can skip building the
- // And and just return the Not directly (pr228980)
- TypePattern p = null;
- TypePattern tp = parseAtomicTypePattern(insideTypeParameters, parameterAnnotationsPossible);
- if (!(ap instanceof AnyAnnotationTypePattern)) {
- p = new NotTypePattern(tp);
- p = new AndTypePattern(setAnnotationPatternForTypePattern(TypePattern.ANY, ap, false), p);
- } else {
- p = new NotTypePattern(tp);
- }
- return p;
- }
- if (maybeEat("(")) {
- int openParenPos = tokenSource.peek(-1).getStart();
- TypePattern p = parseTypePattern(insideTypeParameters, false);
- if ((p instanceof NotTypePattern) && !(ap instanceof AnyAnnotationTypePattern)) {
- // dont set the annotation on it, we don't want the annotation to be
- // considered as part of the not, it is outside the not (pr228980)
- TypePattern tp = setAnnotationPatternForTypePattern(TypePattern.ANY, ap, parameterAnnotationsPossible);
- p = new AndTypePattern(tp, p);
- } else {
- p = setAnnotationPatternForTypePattern(p, ap, parameterAnnotationsPossible);
- }
- eat(")");
- int closeParenPos = tokenSource.peek(-1).getStart();
- boolean isVarArgs = maybeEat("...");
- if (isVarArgs) {
- p.setIsVarArgs(isVarArgs);
- }
- boolean isIncludeSubtypes = maybeEat("+");
- if (isIncludeSubtypes) {
- p.includeSubtypes = true; // need the test because (A+) should not set subtypes to false!
- }
- p.start = openParenPos;
- p.end = closeParenPos;
- return p;
- }
- int startPos = tokenSource.peek().getStart();
- if (ap.start != -1) {
- startPos = ap.start;
- }
- TypePattern p = parseSingleTypePattern(insideTypeParameters);
- int endPos = tokenSource.peek(-1).getEnd();
- p = setAnnotationPatternForTypePattern(p, ap, false);
- p.setLocation(sourceContext, startPos, endPos);
- return p;
- }
-
- private TypePattern setAnnotationPatternForTypePattern(TypePattern t, AnnotationTypePattern ap,
- boolean parameterAnnotationsPattern) {
- TypePattern ret = t;
- if (parameterAnnotationsPattern) {
- ap.setForParameterAnnotationMatch();
- }
- if (ap != AnnotationTypePattern.ANY) {
- if (t == TypePattern.ANY) {
- if (t.annotationPattern == AnnotationTypePattern.ANY) {
- return new AnyWithAnnotationTypePattern(ap);
- } else {
- return new AnyWithAnnotationTypePattern(new AndAnnotationTypePattern(ap, t.annotationPattern));
- }
- // ret = new WildTypePattern(new NamePattern[] { NamePattern.ANY }, false, 0, false, null);
- }
- if (t.annotationPattern == AnnotationTypePattern.ANY) {
- ret.setAnnotationTypePattern(ap);
- } else {
- ret.setAnnotationTypePattern(new AndAnnotationTypePattern(ap, t.annotationPattern)); // ???
- }
- }
- return ret;
- }
-
- public AnnotationTypePattern maybeParseAnnotationPattern() {
- AnnotationTypePattern ret = AnnotationTypePattern.ANY;
- AnnotationTypePattern nextPattern = null;
- while ((nextPattern = maybeParseSingleAnnotationPattern()) != null) {
- if (ret == AnnotationTypePattern.ANY) {
- ret = nextPattern;
- } else {
- ret = new AndAnnotationTypePattern(ret, nextPattern);
- }
- }
- return ret;
- }
-
- // PVAL cope with annotation values at other places in this code
- public AnnotationTypePattern maybeParseSingleAnnotationPattern() {
- AnnotationTypePattern ret = null;
- Map<String, String> values = null;
- // LALR(2) - fix by making "!@" a single token
- int startIndex = tokenSource.getIndex();
- if (maybeEat("!")) {
- if (maybeEat("@")) {
- if (maybeEat("(")) {
- TypePattern p = parseTypePattern();
- ret = new NotAnnotationTypePattern(new WildAnnotationTypePattern(p));
- eat(")");
- return ret;
- } else {
- TypePattern p = parseSingleTypePattern();
- if (maybeEatAdjacent("(")) {
- values = parseAnnotationValues();
- eat(")");
- ret = new NotAnnotationTypePattern(new WildAnnotationTypePattern(p, values));
- } else {
- ret = new NotAnnotationTypePattern(new WildAnnotationTypePattern(p));
- }
- return ret;
- }
- } else {
- tokenSource.setIndex(startIndex); // not for us!
- return ret;
- }
- }
- if (maybeEat("@")) {
- if (maybeEat("(")) {
- TypePattern p = parseTypePattern();
- ret = new WildAnnotationTypePattern(p);
- eat(")");
- return ret;
- } else {
- int atPos = tokenSource.peek(-1).getStart();
- TypePattern p = parseSingleTypePattern();
- if (maybeEatAdjacent("(")) {
- values = parseAnnotationValues();
- eat(")");
- ret = new WildAnnotationTypePattern(p, values);
- } else {
- ret = new WildAnnotationTypePattern(p);
- }
- ret.start = atPos;
- return ret;
- }
- } else {
- tokenSource.setIndex(startIndex); // not for us!
- return ret;
- }
- }
-
- // Parse annotation values. In an expression in @A(a=b,c=d) this method will be
- // parsing the a=b,c=d.)
- public Map<String, String> parseAnnotationValues() {
- Map<String, String> values = new HashMap<String, String>();
- boolean seenDefaultValue = false;
- do {
- String possibleKeyString = parseAnnotationNameValuePattern();
- if (possibleKeyString == null) {
- throw new ParserException("expecting simple literal ", tokenSource.peek(-1));
- }
- // did they specify just a single entry 'v' or a keyvalue pair 'k=v'
- if (maybeEat("=")) {
- // it was a key!
- String valueString = parseAnnotationNameValuePattern();
- if (valueString == null) {
- throw new ParserException("expecting simple literal ", tokenSource.peek(-1));
- }
- values.put(possibleKeyString, valueString);
- } else if (maybeEat("!=")) {
- // it was a key, with a !=
- String valueString = parseAnnotationNameValuePattern();
- if (valueString == null) {
- throw new ParserException("expecting simple literal ", tokenSource.peek(-1));
- }
- // negation is captured by adding a trailing ! to the key name
- values.put(possibleKeyString + "!", valueString);
- } else {
- if (seenDefaultValue) {
- throw new ParserException("cannot specify two default values", tokenSource.peek(-1));
- }
- seenDefaultValue = true;
- values.put("value", possibleKeyString);
- }
- } while (maybeEat(",")); // keep going whilst there are ','
- return values;
- }
-
- public TypePattern parseSingleTypePattern() {
- return parseSingleTypePattern(false);
- }
-
- public TypePattern parseSingleTypePattern(boolean insideTypeParameters) {
- if (insideTypeParameters && maybeEat("?")) {
- return parseGenericsWildcardTypePattern();
- }
- if (allowHasTypePatterns) {
- if (maybeEatIdentifier("hasmethod")) {
- return parseHasMethodTypePattern();
- }
- if (maybeEatIdentifier("hasfield")) {
- return parseHasFieldTypePattern();
- }
- }
-
- // // Check for a type category
- // IToken token = tokenSource.peek();
- // if (token.isIdentifier()) {
- // String category = token.getString();
- // TypeCategoryTypePattern typeIsPattern = null;
- // if (category.equals("isClass")) {
- // typeIsPattern = new TypeCategoryTypePattern(TypeCategoryTypePattern.CLASS);
- // } else if (category.equals("isAspect")) {
- // typeIsPattern = new TypeCategoryTypePattern(TypeCategoryTypePattern.ASPECT);
- // } else if (category.equals("isInterface")) {
- // typeIsPattern = new TypeCategoryTypePattern(TypeCategoryTypePattern.INTERFACE);
- // } else if (category.equals("isInner")) {
- // typeIsPattern = new TypeCategoryTypePattern(TypeCategoryTypePattern.INNER);
- // } else if (category.equals("isAnonymous")) {
- // typeIsPattern = new TypeCategoryTypePattern(TypeCategoryTypePattern.ANONYMOUS);
- // } else if (category.equals("isEnum")) {
- // typeIsPattern = new TypeCategoryTypePattern(TypeCategoryTypePattern.ENUM);
- // } else if (category.equals("isAnnotation")) {
- // typeIsPattern = new TypeCategoryTypePattern(TypeCategoryTypePattern.ANNOTATION);
- // }
- // if (typeIsPattern != null) {
- // tokenSource.next();
- // typeIsPattern.setLocation(tokenSource.getSourceContext(), token.getStart(), token.getEnd());
- // return typeIsPattern;
- // }
- // }
- if (maybeEatIdentifier("is")) {
- int pos = tokenSource.getIndex() - 1;
- TypePattern typeIsPattern = parseIsTypePattern();
- if (typeIsPattern != null) {
- return typeIsPattern;
- }
- // rewind as if we never tried to parse it as a typeIs
- tokenSource.setIndex(pos);
- }
-
- List<NamePattern> names = parseDottedNamePattern();
-
- int dim = 0;
- while (maybeEat("[")) {
- eat("]");
- dim++;
- }
-
- TypePatternList typeParameters = maybeParseTypeParameterList();
- int endPos = tokenSource.peek(-1).getEnd();
-
- boolean includeSubtypes = maybeEat("+");
-
- // TODO do we need to associate the + with either the type or the array?
- while (maybeEat("[")) {
- eat("]");
- dim++;
- }
-
- boolean isVarArgs = maybeEat("...");
-
- // ??? what about the source location of any's????
- if (names.size() == 1 && names.get(0).isAny() && dim == 0 && !isVarArgs && typeParameters == null) {
- return TypePattern.ANY;
- }
-
- // Notice we increase the dimensions if varargs is set. this is to allow type matching to
- // succeed later: The actual signature at runtime of a method declared varargs is an array type of
- // the original declared type (so Integer... becomes Integer[] in the bytecode). So, here for the
- // pattern 'Integer...' we create a WildTypePattern 'Integer[]' with varargs set. If this matches
- // during shadow matching, we confirm that the varargs flags match up before calling it a successful
- // match.
- return new WildTypePattern(names, includeSubtypes, dim + (isVarArgs ? 1 : 0), endPos, isVarArgs, typeParameters);
- }
-
- public TypePattern parseHasMethodTypePattern() {
- int startPos = tokenSource.peek(-1).getStart();
- eat("(");
- SignaturePattern sp = parseMethodOrConstructorSignaturePattern();
- eat(")");
- int endPos = tokenSource.peek(-1).getEnd();
- HasMemberTypePattern ret = new HasMemberTypePattern(sp);
- ret.setLocation(sourceContext, startPos, endPos);
- return ret;
- }
-
- /**
- * Attempt to parse a typeIs(<category>) construct. If it cannot be parsed we just return null and that should cause the caller
- * to reset their position and attempt to consume it in another way. This means we won't have problems here: execution(*
- * typeIs(..)) because someone has decided to call a method the same as our construct.
- *
- * @return a TypeIsTypePattern or null if could not be parsed
- */
- public TypePattern parseIsTypePattern() {
- int startPos = tokenSource.peek(-1).getStart(); // that will be the start of the 'typeIs'
- if (!maybeEatAdjacent("(")) {
- return null;
- }
- IToken token = tokenSource.next();
- TypeCategoryTypePattern typeIsPattern = null;
- if (token.isIdentifier()) {
- String category = token.getString();
- if (category.equals("ClassType")) {
- typeIsPattern = new TypeCategoryTypePattern(TypeCategoryTypePattern.CLASS);
- } else if (category.equals("AspectType")) {
- typeIsPattern = new TypeCategoryTypePattern(TypeCategoryTypePattern.ASPECT);
- } else if (category.equals("InterfaceType")) {
- typeIsPattern = new TypeCategoryTypePattern(TypeCategoryTypePattern.INTERFACE);
- } else if (category.equals("InnerType")) {
- typeIsPattern = new TypeCategoryTypePattern(TypeCategoryTypePattern.INNER);
- } else if (category.equals("AnonymousType")) {
- typeIsPattern = new TypeCategoryTypePattern(TypeCategoryTypePattern.ANONYMOUS);
- } else if (category.equals("EnumType")) {
- typeIsPattern = new TypeCategoryTypePattern(TypeCategoryTypePattern.ENUM);
- } else if (category.equals("AnnotationType")) {
- typeIsPattern = new TypeCategoryTypePattern(TypeCategoryTypePattern.ANNOTATION);
- }
- }
- if (typeIsPattern == null) {
- return null;
- }
- if (!maybeEat(")")) {
- throw new ParserException(")", tokenSource.peek());
- }
- int endPos = tokenSource.peek(-1).getEnd();
- typeIsPattern.setLocation(tokenSource.getSourceContext(), startPos, endPos);
- return typeIsPattern;
- }
-
- // if (names.size() == 1 && !names.get(0).isAny()) {
- // if (maybeEatAdjacent("(")) {
- // if (maybeEat(")")) {
- // // likely to be one of isClass()/isInterface()/isInner()/isAnonymous()/isAspect()
- // if (names.size() == 1) {
- // NamePattern np = names.get(0);
- // String simpleName = np.maybeGetSimpleName();
- // if (simpleName != null) {
-
- // return new TypeCategoryTypePattern(TypeCategoryTypePattern.ANNOTATION, np);
- // } else {
- // throw new ParserException(
- // "not a supported type category, supported are isClass/isInterface/isEnum/isAnnotation/isInner/isAnonymous",
- // tokenSource.peek(-3));
- // }
- // }
- // int stop = 1;
- // // return new WildTypePattern(names, includeSubtypes, dim + (isVarArgs ? 1 : 0), endPos, isVarArgs,
- // // typeParameters);
- // }
- // } else {
- // throw new ParserException("category type pattern is missing closing parentheses", tokenSource.peek(-2));
- // }
- // }
- // }
-
- public TypePattern parseHasFieldTypePattern() {
- int startPos = tokenSource.peek(-1).getStart();
- eat("(");
- SignaturePattern sp = parseFieldSignaturePattern();
- eat(")");
- int endPos = tokenSource.peek(-1).getEnd();
- HasMemberTypePattern ret = new HasMemberTypePattern(sp);
- ret.setLocation(sourceContext, startPos, endPos);
- return ret;
- }
-
- public TypePattern parseGenericsWildcardTypePattern() {
- List<NamePattern> names = new ArrayList<NamePattern>();
- names.add(new NamePattern("?"));
- TypePattern upperBound = null;
- TypePattern[] additionalInterfaceBounds = new TypePattern[0];
- TypePattern lowerBound = null;
- if (maybeEatIdentifier("extends")) {
- upperBound = parseTypePattern(false, false);
- additionalInterfaceBounds = maybeParseAdditionalInterfaceBounds();
- }
- if (maybeEatIdentifier("super")) {
- lowerBound = parseTypePattern(false, false);
- }
- int endPos = tokenSource.peek(-1).getEnd();
- return new WildTypePattern(names, false, 0, endPos, false, null, upperBound, additionalInterfaceBounds, lowerBound);
- }
-
- // private AnnotationTypePattern completeAnnotationPattern(AnnotationTypePattern p) {
- // if (maybeEat("&&")) {
- // return new AndAnnotationTypePattern(p,parseNotOrAnnotationPattern());
- // }
- // if (maybeEat("||")) {
- // return new OrAnnotationTypePattern(p,parseAnnotationTypePattern());
- // }
- // return p;
- // }
- //
- // protected AnnotationTypePattern parseAnnotationTypePattern() {
- // AnnotationTypePattern ap = parseAtomicAnnotationPattern();
- // if (maybeEat("&&")) {
- // ap = new AndAnnotationTypePattern(ap, parseNotOrAnnotationPattern());
- // }
- //
- // if (maybeEat("||")) {
- // ap = new OrAnnotationTypePattern(ap, parseAnnotationTypePattern());
- // }
- // return ap;
- // }
- //
- // private AnnotationTypePattern parseNotOrAnnotationPattern() {
- // AnnotationTypePattern p = parseAtomicAnnotationPattern();
- // if (maybeEat("&&")) {
- // p = new AndAnnotationTypePattern(p,parseAnnotationTypePattern());
- // }
- // return p;
- // }
-
- protected ExactAnnotationTypePattern parseAnnotationNameOrVarTypePattern() {
- ExactAnnotationTypePattern p = null;
- int startPos = tokenSource.peek().getStart();
- if (maybeEat("@")) {
- throw new ParserException("@Foo form was deprecated in AspectJ 5 M2: annotation name or var ", tokenSource.peek(-1));
- }
- p = parseSimpleAnnotationName();
- int endPos = tokenSource.peek(-1).getEnd();
- p.setLocation(sourceContext, startPos, endPos);
- // For optimized syntax that allows binding directly to annotation values (pr234943)
- if (maybeEat("(")) {
- String formalName = parseIdentifier();
- p = new ExactAnnotationFieldTypePattern(p, formalName);
- eat(")");
- }
- return p;
- }
-
- /**
- * @return
- */
- private ExactAnnotationTypePattern parseSimpleAnnotationName() {
- // the @ has already been eaten...
- ExactAnnotationTypePattern p;
- StringBuffer annotationName = new StringBuffer();
- annotationName.append(parseIdentifier());
- while (maybeEat(".")) {
- annotationName.append('.');
- annotationName.append(parseIdentifier());
- }
- UnresolvedType type = UnresolvedType.forName(annotationName.toString());
- p = new ExactAnnotationTypePattern(type, null);
- return p;
- }
-
- // private AnnotationTypePattern parseAtomicAnnotationPattern() {
- // if (maybeEat("!")) {
- // //int startPos = tokenSource.peek(-1).getStart();
- // //??? we lose source location for true start of !type
- // AnnotationTypePattern p = new NotAnnotationTypePattern(parseAtomicAnnotationPattern());
- // return p;
- // }
- // if (maybeEat("(")) {
- // AnnotationTypePattern p = parseAnnotationTypePattern();
- // eat(")");
- // return p;
- // }
- // int startPos = tokenSource.peek().getStart();
- // eat("@");
- // StringBuffer annotationName = new StringBuffer();
- // annotationName.append(parseIdentifier());
- // while (maybeEat(".")) {
- // annotationName.append('.');
- // annotationName.append(parseIdentifier());
- // }
- // UnresolvedType type = UnresolvedType.forName(annotationName.toString());
- // AnnotationTypePattern p = new ExactAnnotationTypePattern(type);
- // int endPos = tokenSource.peek(-1).getEnd();
- // p.setLocation(sourceContext, startPos, endPos);
- // return p;
- // }
-
- public List<NamePattern> parseDottedNamePattern() {
- List<NamePattern> names = new ArrayList<NamePattern>();
- StringBuffer buf = new StringBuffer();
- IToken previous = null;
- boolean justProcessedEllipsis = false; // Remember if we just dealt with an ellipsis (PR61536)
- boolean justProcessedDot = false;
- boolean onADot = false;
-
- while (true) {
- IToken tok = null;
- int startPos = tokenSource.peek().getStart();
- String afterDot = null;
- while (true) {
- if (previous != null && previous.getString().equals(".")) {
- justProcessedDot = true;
- }
- tok = tokenSource.peek();
- onADot = (tok.getString().equals("."));
- if (previous != null) {
- if (!isAdjacent(previous, tok)) {
- break;
- }
- }
- if (tok.getString() == "*" || (tok.isIdentifier() && tok.getString() != "...")) {
- buf.append(tok.getString());
- } else if (tok.getString() == "...") {
- break;
- } else if (tok.getLiteralKind() != null) {
- // System.err.println("literal kind: " + tok.getString());
- String s = tok.getString();
- int dot = s.indexOf('.');
- if (dot != -1) {
- buf.append(s.substring(0, dot));
- afterDot = s.substring(dot + 1);
- previous = tokenSource.next();
- break;
- }
- buf.append(s); // ??? so-so
- } else {
- break;
- }
- previous = tokenSource.next();
- // XXX need to handle floats and other fun stuff
- }
- int endPos = tokenSource.peek(-1).getEnd();
- if (buf.length() == 0 && names.isEmpty()) {
- throw new ParserException("name pattern", tok);
- }
-
- if (buf.length() == 0 && justProcessedEllipsis) {
- throw new ParserException("name pattern cannot finish with ..", tok);
- }
- if (buf.length() == 0 && justProcessedDot && !onADot) {
- throw new ParserException("name pattern cannot finish with .", tok);
- }
-
- if (buf.length() == 0) {
- names.add(NamePattern.ELLIPSIS);
- justProcessedEllipsis = true;
- } else {
- checkLegalName(buf.toString(), previous);
- NamePattern ret = new NamePattern(buf.toString());
- ret.setLocation(sourceContext, startPos, endPos);
- names.add(ret);
- justProcessedEllipsis = false;
- }
-
- if (afterDot == null) {
- buf.setLength(0);
- // no elipsis or dotted name part
- if (!maybeEat(".")) {
- break;
- // go on
- } else {
- previous = tokenSource.peek(-1);
- }
- } else {
- buf.setLength(0);
- buf.append(afterDot);
- afterDot = null;
- }
- }
- // System.err.println("parsed: " + names);
- return names;
- }
-
- // supported form 'a.b.c.d' or just 'a'
- public String parseAnnotationNameValuePattern() {
- StringBuffer buf = new StringBuffer();
- IToken tok;
- // int startPos =
- tokenSource.peek().getStart();
- boolean dotOK = false;
- int depth = 0;
- while (true) {
- tok = tokenSource.peek();
- // keep going until we hit ')' or '=' or ','
- if (tok.getString() == ")" && depth == 0) {
- break;
- }
- if (tok.getString() == "!=" && depth == 0) {
- break;
- }
- if (tok.getString() == "=" && depth == 0) {
- break;
- }
- if (tok.getString() == "," && depth == 0) {
- break;
- }
- if (tok == IToken.EOF) {
- throw new ParserException("eof", tokenSource.peek());
- }
-
- // keep track of nested brackets
- if (tok.getString() == "(") {
- depth++;
- }
- if (tok.getString() == ")") {
- depth--;
- }
- if (tok.getString() == "{") {
- depth++;
- }
- if (tok.getString() == "}") {
- depth--;
- }
-
- if (tok.getString() == "." && !dotOK) {
- throw new ParserException("dot not expected", tok);
- }
- buf.append(tok.getString());
- tokenSource.next();
- dotOK = true;
- }
- return buf.toString();
- }
-
- public NamePattern parseNamePattern() {
- StringBuffer buf = new StringBuffer();
- IToken previous = null;
- IToken tok;
- int startPos = tokenSource.peek().getStart();
- while (true) {
- tok = tokenSource.peek();
- if (previous != null) {
- if (!isAdjacent(previous, tok)) {
- break;
- }
- }
- if (tok.getString() == "*" || tok.isIdentifier()) {
- buf.append(tok.getString());
- } else if (tok.getLiteralKind() != null) {
- // System.err.println("literal kind: " + tok.getString());
- String s = tok.getString();
- if (s.indexOf('.') != -1) {
- break;
- }
- buf.append(s); // ??? so-so
- } else {
- break;
- }
- previous = tokenSource.next();
- // XXX need to handle floats and other fun stuff
- }
- int endPos = tokenSource.peek(-1).getEnd();
- if (buf.length() == 0) {
- throw new ParserException("name pattern", tok);
- }
-
- checkLegalName(buf.toString(), previous);
- NamePattern ret = new NamePattern(buf.toString());
- ret.setLocation(sourceContext, startPos, endPos);
- return ret;
- }
-
- private void checkLegalName(String s, IToken tok) {
- char ch = s.charAt(0);
- if (!(ch == '*' || Character.isJavaIdentifierStart(ch))) {
- throw new ParserException("illegal identifier start (" + ch + ")", tok);
- }
-
- for (int i = 1, len = s.length(); i < len; i++) {
- ch = s.charAt(i);
- if (!(ch == '*' || Character.isJavaIdentifierPart(ch))) {
- throw new ParserException("illegal identifier character (" + ch + ")", tok);
- }
- }
-
- }
-
- private boolean isAdjacent(IToken first, IToken second) {
- return first.getEnd() == second.getStart() - 1;
- }
-
- public ModifiersPattern parseModifiersPattern() {
- int requiredFlags = 0;
- int forbiddenFlags = 0;
- int start;
- while (true) {
- start = tokenSource.getIndex();
- boolean isForbidden = false;
- isForbidden = maybeEat("!");
- IToken t = tokenSource.next();
- int flag = ModifiersPattern.getModifierFlag(t.getString());
- if (flag == -1) {
- break;
- }
- if (isForbidden) {
- forbiddenFlags |= flag;
- } else {
- requiredFlags |= flag;
- }
- }
-
- tokenSource.setIndex(start);
- if (requiredFlags == 0 && forbiddenFlags == 0) {
- return ModifiersPattern.ANY;
- } else {
- return new ModifiersPattern(requiredFlags, forbiddenFlags);
- }
- }
-
- public TypePatternList parseArgumentsPattern(boolean parameterAnnotationsPossible) {
- List<TypePattern> patterns = new ArrayList<TypePattern>();
- eat("(");
-
- // ()
- if (maybeEat(")")) {
- return new TypePatternList();
- }
-
- do {
- if (maybeEat(".")) { // ..
- eat(".");
- patterns.add(TypePattern.ELLIPSIS);
- } else {
- patterns.add(parseTypePattern(false, parameterAnnotationsPossible));
- }
- } while (maybeEat(","));
- eat(")");
- return new TypePatternList(patterns);
- }
-
- public AnnotationPatternList parseArgumentsAnnotationPattern() {
- List<AnnotationTypePattern> patterns = new ArrayList<AnnotationTypePattern>();
- eat("(");
- if (maybeEat(")")) {
- return new AnnotationPatternList();
- }
-
- do {
- if (maybeEat(".")) {
- eat(".");
- patterns.add(AnnotationTypePattern.ELLIPSIS);
- } else if (maybeEat("*")) {
- patterns.add(AnnotationTypePattern.ANY);
- } else {
- patterns.add(parseAnnotationNameOrVarTypePattern());
- }
- } while (maybeEat(","));
- eat(")");
- return new AnnotationPatternList(patterns);
- }
-
- public ThrowsPattern parseOptionalThrowsPattern() {
- IToken t = tokenSource.peek();
- if (t.isIdentifier() && t.getString().equals("throws")) {
- tokenSource.next();
- List<TypePattern> required = new ArrayList<TypePattern>();
- List<TypePattern> forbidden = new ArrayList<TypePattern>();
- do {
- boolean isForbidden = maybeEat("!");
- // ???might want an error for a second ! without a paren
- TypePattern p = parseTypePattern();
- if (isForbidden) {
- forbidden.add(p);
- } else {
- required.add(p);
- }
- } while (maybeEat(","));
- return new ThrowsPattern(new TypePatternList(required), new TypePatternList(forbidden));
- }
- return ThrowsPattern.ANY;
- }
-
- public SignaturePattern parseMethodOrConstructorSignaturePattern() {
- int startPos = tokenSource.peek().getStart();
- AnnotationTypePattern annotationPattern = maybeParseAnnotationPattern();
- ModifiersPattern modifiers = parseModifiersPattern();
- TypePattern returnType = parseTypePattern(false, false);
-
- TypePattern declaringType;
- NamePattern name = null;
- MemberKind kind;
- // here we can check for 'new'
- if (maybeEatNew(returnType)) {
- kind = Member.CONSTRUCTOR;
- if (returnType.toString().length() == 0) {
- declaringType = TypePattern.ANY;
- } else {
- declaringType = returnType;
- }
- returnType = TypePattern.ANY;
- name = NamePattern.ANY;
- } else {
- kind = Member.METHOD;
- IToken nameToken = tokenSource.peek();
- declaringType = parseTypePattern(false, false);
- if (maybeEat(".")) {
- nameToken = tokenSource.peek();
- name = parseNamePattern();
- } else {
- name = tryToExtractName(declaringType);
- if (declaringType.toString().equals("")) {
- declaringType = TypePattern.ANY;
- }
- }
- if (name == null) {
- throw new ParserException("name pattern", tokenSource.peek());
- }
- String simpleName = name.maybeGetSimpleName();
- // XXX should add check for any Java keywords
- if (simpleName != null && simpleName.equals("new")) {
- throw new ParserException("method name (not constructor)", nameToken);
- }
- }
-
- TypePatternList parameterTypes = parseArgumentsPattern(true);
-
- ThrowsPattern throwsPattern = parseOptionalThrowsPattern();
- SignaturePattern ret = new SignaturePattern(kind, modifiers, returnType, declaringType, name, parameterTypes,
- throwsPattern, annotationPattern);
- int endPos = tokenSource.peek(-1).getEnd();
- ret.setLocation(sourceContext, startPos, endPos);
- return ret;
- }
-
- private boolean maybeEatNew(TypePattern returnType) {
- if (returnType instanceof WildTypePattern) {
- WildTypePattern p = (WildTypePattern) returnType;
- if (p.maybeExtractName("new")) {
- return true;
- }
- }
- int start = tokenSource.getIndex();
- if (maybeEat(".")) {
- String id = maybeEatIdentifier();
- if (id != null && id.equals("new")) {
- return true;
- }
- tokenSource.setIndex(start);
- }
-
- return false;
- }
-
- public ISignaturePattern parseMaybeParenthesizedFieldSignaturePattern() {
- boolean negated = tokenSource.peek().getString().equals("!") && tokenSource.peek(1).getString().equals("(");
- if (negated) {
- eat("!");
- }
- ISignaturePattern result = null;
- if (maybeEat("(")) {
- result = parseCompoundFieldSignaturePattern();
- eat(")", "missing ')' - unbalanced parentheses around field signature pattern in declare @field");
- if (negated) {
- result = new NotSignaturePattern(result);
- }
- } else {
- result = parseFieldSignaturePattern();
- }
- return result;
- }
-
- public ISignaturePattern parseMaybeParenthesizedMethodOrConstructorSignaturePattern(boolean isMethod) {
- boolean negated = tokenSource.peek().getString().equals("!") && tokenSource.peek(1).getString().equals("(");
- if (negated) {
- eat("!");
- }
- ISignaturePattern result = null;
- if (maybeEat("(")) {
- result = parseCompoundMethodOrConstructorSignaturePattern(isMethod);
- eat(")", "missing ')' - unbalanced parentheses around method/ctor signature pattern in declare annotation");
- if (negated) {
- result = new NotSignaturePattern(result);
- }
- } else {
- SignaturePattern sp = parseMethodOrConstructorSignaturePattern();
- boolean isConstructorPattern = (sp.getKind() == Member.CONSTRUCTOR);
- if (isMethod && isConstructorPattern) {
- throw new ParserException("method signature pattern", tokenSource.peek(-1));
- }
- if (!isMethod && !isConstructorPattern) {
- throw new ParserException("constructor signature pattern", tokenSource.peek(-1));
- }
- result = sp;
- }
-
- return result;
- }
-
- public SignaturePattern parseFieldSignaturePattern() {
- int startPos = tokenSource.peek().getStart();
-
- // TypePatternList followMe = TypePatternList.ANY;
-
- AnnotationTypePattern annotationPattern = maybeParseAnnotationPattern();
- ModifiersPattern modifiers = parseModifiersPattern();
- TypePattern returnType = parseTypePattern();
- TypePattern declaringType = parseTypePattern();
- NamePattern name;
- // System.err.println("parsed field: " + declaringType.toString());
- if (maybeEat(".")) {
- name = parseNamePattern();
- } else {
- name = tryToExtractName(declaringType);
- if (name == null) {
- throw new ParserException("name pattern", tokenSource.peek());
- }
- if (declaringType.toString().equals("")) {
- declaringType = TypePattern.ANY;
- }
- }
- SignaturePattern ret = new SignaturePattern(Member.FIELD, modifiers, returnType, declaringType, name, TypePatternList.ANY,
- ThrowsPattern.ANY, annotationPattern);
-
- int endPos = tokenSource.peek(-1).getEnd();
- ret.setLocation(sourceContext, startPos, endPos);
- return ret;
- }
-
- private NamePattern tryToExtractName(TypePattern nextType) {
- if (nextType == TypePattern.ANY) {
- return NamePattern.ANY;
- } else if (nextType instanceof WildTypePattern) {
- WildTypePattern p = (WildTypePattern) nextType;
- return p.extractName();
- } else {
- return null;
- }
- }
-
- /**
- * Parse type variable declarations for a generic method or at the start of a signature pointcut to identify type variable names
- * in a generic type.
- *
- * @param includeParameterizedTypes
- * @return
- */
- public TypeVariablePatternList maybeParseTypeVariableList() {
- if (!maybeEat("<")) {
- return null;
- }
- List<TypeVariablePattern> typeVars = new ArrayList<TypeVariablePattern>();
- TypeVariablePattern t = parseTypeVariable();
- typeVars.add(t);
- while (maybeEat(",")) {
- TypeVariablePattern nextT = parseTypeVariable();
- typeVars.add(nextT);
- }
- eat(">");
- TypeVariablePattern[] tvs = new TypeVariablePattern[typeVars.size()];
- typeVars.toArray(tvs);
- return new TypeVariablePatternList(tvs);
- }
-
- // of the form execution<T,S,V> - allows identifiers only
- public String[] maybeParseSimpleTypeVariableList() {
- if (!maybeEat("<")) {
- return null;
- }
- List<String> typeVarNames = new ArrayList<String>();
- do {
- typeVarNames.add(parseIdentifier());
- } while (maybeEat(","));
- eat(">", "',' or '>'");
- String[] tvs = new String[typeVarNames.size()];
- typeVarNames.toArray(tvs);
- return tvs;
- }
-
- public TypePatternList maybeParseTypeParameterList() {
- if (!maybeEat("<")) {
- return null;
- }
- List<TypePattern> typePats = new ArrayList<TypePattern>();
- do {
- TypePattern tp = parseTypePattern(true, false);
- typePats.add(tp);
- } while (maybeEat(","));
- eat(">");
- TypePattern[] tps = new TypePattern[typePats.size()];
- typePats.toArray(tps);
- return new TypePatternList(tps);
- }
-
- public TypeVariablePattern parseTypeVariable() {
- TypePattern upperBound = null;
- TypePattern[] additionalInterfaceBounds = null;
- TypePattern lowerBound = null;
- String typeVariableName = parseIdentifier();
- if (maybeEatIdentifier("extends")) {
- upperBound = parseTypePattern();
- additionalInterfaceBounds = maybeParseAdditionalInterfaceBounds();
- } else if (maybeEatIdentifier("super")) {
- lowerBound = parseTypePattern();
- }
- return new TypeVariablePattern(typeVariableName, upperBound, additionalInterfaceBounds, lowerBound);
- }
-
- private TypePattern[] maybeParseAdditionalInterfaceBounds() {
- List<TypePattern> boundsList = new ArrayList<TypePattern>();
- while (maybeEat("&")) {
- TypePattern tp = parseTypePattern();
- boundsList.add(tp);
- }
- if (boundsList.size() == 0) {
- return null;
- }
- TypePattern[] ret = new TypePattern[boundsList.size()];
- boundsList.toArray(ret);
- return ret;
- }
-
- public String parsePossibleStringSequence(boolean shouldEnd) {
- StringBuffer result = new StringBuffer();
-
- IToken token = tokenSource.next();
- if (token.getLiteralKind() == null) {
- throw new ParserException("string", token);
- }
- while (token.getLiteralKind().equals("string")) {
- result.append(token.getString());
- boolean plus = maybeEat("+");
- if (!plus) {
- break;
- }
- token = tokenSource.next();
- if (token.getLiteralKind() == null) {
- throw new ParserException("string", token);
- }
- }
- eatIdentifier(";");
- IToken t = tokenSource.next();
- if (shouldEnd && t != IToken.EOF) {
- throw new ParserException("<string>;", token);
- }
- // bug 125027: since we've eaten the ";" we need to set the index
- // to be one less otherwise the end position isn't set correctly.
- int currentIndex = tokenSource.getIndex();
- tokenSource.setIndex(currentIndex - 1);
-
- return result.toString();
-
- }
-
- public String parseStringLiteral() {
- IToken token = tokenSource.next();
- String literalKind = token.getLiteralKind();
- if (literalKind == "string") {
- return token.getString();
- }
-
- throw new ParserException("string", token);
- }
-
- public String parseIdentifier() {
- IToken token = tokenSource.next();
- if (token.isIdentifier()) {
- return token.getString();
- }
- throw new ParserException("identifier", token);
- }
-
- public void eatIdentifier(String expectedValue) {
- IToken next = tokenSource.next();
- if (!next.getString().equals(expectedValue)) {
- throw new ParserException(expectedValue, next);
- }
- }
-
- public boolean maybeEatIdentifier(String expectedValue) {
- IToken next = tokenSource.peek();
- if (next.getString().equals(expectedValue)) {
- tokenSource.next();
- return true;
- } else {
- return false;
- }
- }
-
- public void eat(String expectedValue) {
- eat(expectedValue, expectedValue);
- }
-
- private void eat(String expectedValue, String expectedMessage) {
- IToken next = nextToken();
- if (next.getString() != expectedValue) {
- if (expectedValue.equals(">") && next.getString().startsWith(">")) {
- // handle problem of >> and >>> being lexed as single tokens
- pendingRightArrows = BasicToken.makeLiteral(next.getString().substring(1).intern(), "string", next.getStart() + 1,
- next.getEnd());
- return;
- }
- throw new ParserException(expectedMessage, next);
- }
- }
-
- private IToken pendingRightArrows;
-
- private IToken nextToken() {
- if (pendingRightArrows != null) {
- IToken ret = pendingRightArrows;
- pendingRightArrows = null;
- return ret;
- } else {
- return tokenSource.next();
- }
- }
-
- public boolean maybeEatAdjacent(String token) {
- IToken next = tokenSource.peek();
- if (next.getString() == token) {
- if (isAdjacent(tokenSource.peek(-1), next)) {
- tokenSource.next();
- return true;
- }
- }
- return false;
- }
-
- public boolean maybeEat(String token) {
- IToken next = tokenSource.peek();
- if (next.getString() == token) {
- tokenSource.next();
- return true;
- } else {
- return false;
- }
- }
-
- public String maybeEatIdentifier() {
- IToken next = tokenSource.peek();
- if (next.isIdentifier()) {
- tokenSource.next();
- return next.getString();
- } else {
- return null;
- }
- }
-
- public boolean peek(String token) {
- IToken next = tokenSource.peek();
- return next.getString() == token;
- }
-
- public void checkEof() {
- IToken last = tokenSource.next();
- if (last != IToken.EOF) {
- throw new ParserException("unexpected pointcut element: " + last.toString(), last);
- }
- }
-
- public PatternParser(String data) {
- this(BasicTokenSource.makeTokenSource(data, null));
- }
-
- public PatternParser(String data, ISourceContext context) {
- this(BasicTokenSource.makeTokenSource(data, context));
- }
- }
|