From 4f1ce6df3b3f3fb2d6186d08438952df4cadc8a3 Mon Sep 17 00:00:00 2001 From: avasseur Date: Wed, 8 Jun 2005 16:19:16 +0000 Subject: [PATCH] @style if support, parser support for if() / if(true)/ if(false) [might lead to issue with code style to allow "if()" ) --- .../systemtest/ajc150/ataspectj/misuse.xml | 2 +- weaver/src/org/aspectj/weaver/IntMap.java | 6 +- .../weaver/PerObjectInterfaceTypeMunger.java | 165 ++++--------- .../weaver/PerTypeWithinTargetTypeMunger.java | 3 - .../weaver/ResolvedPointcutDefinition.java | 29 ++- .../aspectj/weaver/bcel/AtAjAttributes.java | 41 ++-- .../aspectj/weaver/patterns/ExposedState.java | 2 +- .../aspectj/weaver/patterns/IfPointcut.java | 221 +++++++++++++----- .../weaver/patterns/PatternParser.java | 39 +++- .../PerThisOrTargetPointcutVisitor.java | 2 - .../weaver/patterns/PointcutVisitor.java | 12 +- .../aspectj/weaver/tools/PointcutParser.java | 7 +- weaver/testdata/visitor.pointcuts.txt | 57 +++++ .../weaver/tools/PointcutParserTest.java | 8 +- 14 files changed, 379 insertions(+), 215 deletions(-) diff --git a/tests/src/org/aspectj/systemtest/ajc150/ataspectj/misuse.xml b/tests/src/org/aspectj/systemtest/ajc150/ataspectj/misuse.xml index f78aa87b3..d0204141a 100644 --- a/tests/src/org/aspectj/systemtest/ajc150/ataspectj/misuse.xml +++ b/tests/src/org/aspectj/systemtest/ajc150/ataspectj/misuse.xml @@ -21,7 +21,7 @@ - + diff --git a/weaver/src/org/aspectj/weaver/IntMap.java b/weaver/src/org/aspectj/weaver/IntMap.java index 4025a6211..f8646c8e3 100644 --- a/weaver/src/org/aspectj/weaver/IntMap.java +++ b/weaver/src/org/aspectj/weaver/IntMap.java @@ -38,7 +38,11 @@ public class IntMap { public ResolvedPointcutDefinition peekEnclosingDefinitition() { - return (ResolvedPointcutDefinition)enclosingDefinition.get(enclosingDefinition.size()-1); + try { + return (ResolvedPointcutDefinition)enclosingDefinition.get(enclosingDefinition.size()-1); + } catch (IndexOutOfBoundsException e) { + return null; + } } diff --git a/weaver/src/org/aspectj/weaver/PerObjectInterfaceTypeMunger.java b/weaver/src/org/aspectj/weaver/PerObjectInterfaceTypeMunger.java index 99ce3bd50..c044edb29 100644 --- a/weaver/src/org/aspectj/weaver/PerObjectInterfaceTypeMunger.java +++ b/weaver/src/org/aspectj/weaver/PerObjectInterfaceTypeMunger.java @@ -1,138 +1,67 @@ /* ******************************************************************* * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC). - * All rights reserved. - * This program and the accompanying materials are made available - * under the terms of the Common Public License v1.0 - * which accompanies this distribution and is available at - * http://www.eclipse.org/legal/cpl-v10.html - * - * Contributors: - * PARC initial implementation + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Common Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * PARC initial implementation + * Alexandre Vasseur rearchitected for #75442 finer grained matching * ******************************************************************/ - - package org.aspectj.weaver; -import java.io.DataOutputStream; -import java.io.IOException; -import java.util.Map; -import java.util.WeakHashMap; -import java.util.List; -import java.util.Set; -import java.util.HashSet; -import java.util.HashMap; - -import org.aspectj.weaver.patterns.Pointcut; -import org.aspectj.weaver.patterns.FastMatchInfo; -import org.aspectj.weaver.patterns.PerClause; -import org.aspectj.weaver.patterns.PointcutVisitor; -import org.aspectj.weaver.patterns.PatternNode; -import org.aspectj.weaver.patterns.PerThisOrTargetPointcutVisitor; +import org.aspectj.weaver.patterns.PerFromSuper; import org.aspectj.weaver.patterns.PerObject; +import org.aspectj.weaver.patterns.PerThisOrTargetPointcutVisitor; +import org.aspectj.weaver.patterns.Pointcut; import org.aspectj.weaver.patterns.TypePattern; -import org.aspectj.weaver.patterns.PerFromSuper; -import org.aspectj.util.FuzzyBoolean; - -public class PerObjectInterfaceTypeMunger extends ResolvedTypeMunger { - - // key is advisedType, value is Set of aspect type that advise the type and are perObject - public static Map s_advisedTypeToAspects = new HashMap(); - public static void registerAsAdvisedBy(ResolvedTypeX matchType, ResolvedTypeX aspectType) { - if (PerClause.PEROBJECT.equals(aspectType.getPerClause().getKind())) { - Set aspects = (Set)s_advisedTypeToAspects.get(matchType); - if (aspects == null) { - aspects = new HashSet(1); - s_advisedTypeToAspects.put(matchType, aspects); - } - aspects.add(aspectType); - } - } - public static void unregisterFromAsAdvisedBy(ResolvedTypeX matchType) { - s_advisedTypeToAspects.remove(matchType); - } - - private ResolvedMember getMethod; - private ResolvedMember setMethod; - private TypeX aspectType; - private TypeX interfaceType; - private Pointcut testPointcut; +import java.io.DataOutputStream; +import java.io.IOException; - public PerObjectInterfaceTypeMunger(TypeX aspectType, Pointcut testPointcut) { - super(PerObjectInterface, null); - this.aspectType = aspectType; - this.testPointcut = testPointcut; - this.interfaceType = AjcMemberMaker.perObjectInterfaceType(aspectType); - this.getMethod = AjcMemberMaker.perObjectInterfaceGet(aspectType); - this.setMethod = AjcMemberMaker.perObjectInterfaceSet(aspectType); - } - - - public void write(DataOutputStream s) throws IOException { - throw new RuntimeException("shouldn't be serialized"); - } - public TypeX getAspectType() { - return aspectType; - } - - public ResolvedMember getGetMethod() { - return getMethod; - } - - public TypeX getInterfaceType() { - return interfaceType; - } +public class PerObjectInterfaceTypeMunger extends ResolvedTypeMunger { - public ResolvedMember getSetMethod() { - return setMethod; - } + private final TypeX interfaceType; + private final Pointcut testPointcut; + private TypePattern lazyTestTypePattern; - public Pointcut getTestPointcut() { - return testPointcut; - } - - public boolean matches(ResolvedTypeX matchType, ResolvedTypeX aspectType) { - if (matchType.isInterface()) return false; + public PerObjectInterfaceTypeMunger(TypeX aspectType, Pointcut testPointcut) { + super(PerObjectInterface, null); + this.testPointcut = testPointcut; + this.interfaceType = AjcMemberMaker.perObjectInterfaceType(aspectType); + } - //FIXME AV - cache that - final boolean isPerThis; - if (aspectType.getPerClause() instanceof PerFromSuper) { - PerFromSuper ps = (PerFromSuper) aspectType.getPerClause(); - isPerThis = ((PerObject)ps.lookupConcretePerClause(aspectType)).isThis(); - } else { - isPerThis = ((PerObject)aspectType.getPerClause()).isThis(); + private TypePattern getTestTypePattern(ResolvedTypeX aspectType) { + if (lazyTestTypePattern == null) { + final boolean isPerThis; + if (aspectType.getPerClause() instanceof PerFromSuper) { + PerFromSuper ps = (PerFromSuper) aspectType.getPerClause(); + isPerThis = ((PerObject) ps.lookupConcretePerClause(aspectType)).isThis(); + } else { + isPerThis = ((PerObject) aspectType.getPerClause()).isThis(); + } + PerThisOrTargetPointcutVisitor v = new PerThisOrTargetPointcutVisitor(!isPerThis, aspectType); + lazyTestTypePattern = v.getPerTypePointcut(testPointcut); } - PerThisOrTargetPointcutVisitor v = new PerThisOrTargetPointcutVisitor( - !isPerThis, - aspectType - ); - TypePattern tp = v.getPerTypePointcut(testPointcut); - - if (true) return tp.matchesStatically(matchType); - - - //FIXME ATAJ waiting Andy patch... - // comment from Andy - this is hard to fix... - - // right now I filter @AJ aspect else it end up with duplicate members - //return !matchType.isInterface() && !matchType.isAnnotationStyleAspect(); - Set aspects = (Set)s_advisedTypeToAspects.get(matchType); - if (aspects == null) { - //return false; - // FIXME AV - #75442 see thread - // back off on old style : it can happen for perTarget that target type is presented first to the weaver - // while caller side is not thus we have advisedTypeToAspects still empty.. + return lazyTestTypePattern; + } - // note: needed only for perTarget if lateMunger is used (see PerObject) - return !matchType.isInterface() && !matchType.isAnnotationStyleAspect(); - } else { - return aspects.contains(aspectType); - } + public void write(DataOutputStream s) throws IOException { + throw new RuntimeException("shouldn't be serialized"); + } + public TypeX getInterfaceType() { + return interfaceType; } - private FuzzyBoolean isWithinType(ResolvedTypeX type) { - return testPointcut.fastMatch(new FastMatchInfo(type, null)); + public Pointcut getTestPointcut() { + return testPointcut; } + public boolean matches(ResolvedTypeX matchType, ResolvedTypeX aspectType) { + if (matchType.isInterface()) return false; + return getTestTypePattern(aspectType).matchesStatically(matchType); + } } diff --git a/weaver/src/org/aspectj/weaver/PerTypeWithinTargetTypeMunger.java b/weaver/src/org/aspectj/weaver/PerTypeWithinTargetTypeMunger.java index 965d7717e..107898a2d 100644 --- a/weaver/src/org/aspectj/weaver/PerTypeWithinTargetTypeMunger.java +++ b/weaver/src/org/aspectj/weaver/PerTypeWithinTargetTypeMunger.java @@ -21,17 +21,14 @@ import org.aspectj.weaver.patterns.Pointcut; // PTWIMPL Target type munger adds the localAspectOf() method public class PerTypeWithinTargetTypeMunger extends ResolvedTypeMunger { - private ResolvedMember localAspectOfMethod; private TypeX aspectType; private PerTypeWithin testPointcut; - public PerTypeWithinTargetTypeMunger(TypeX aspectType, PerTypeWithin testPointcut) { super(PerTypeWithinInterface, null); this.aspectType = aspectType; this.testPointcut = testPointcut; } - public void write(DataOutputStream s) throws IOException { throw new RuntimeException("shouldn't be serialized"); diff --git a/weaver/src/org/aspectj/weaver/ResolvedPointcutDefinition.java b/weaver/src/org/aspectj/weaver/ResolvedPointcutDefinition.java index 21af036b5..79f7689ce 100644 --- a/weaver/src/org/aspectj/weaver/ResolvedPointcutDefinition.java +++ b/weaver/src/org/aspectj/weaver/ResolvedPointcutDefinition.java @@ -21,19 +21,40 @@ import org.aspectj.weaver.patterns.Pointcut; public class ResolvedPointcutDefinition extends ResolvedMember { private Pointcut pointcut; - - public ResolvedPointcutDefinition( + + public ResolvedPointcutDefinition( + TypeX declaringType, + int modifiers, + String name, + TypeX[] parameterTypes, + Pointcut pointcut) + { + this(declaringType, modifiers, name, parameterTypes, ResolvedTypeX.VOID, pointcut); + } + + /** + * An instance which can be given a specific returnType, used f.e. in if() pointcut for @AJ + * + * @param declaringType + * @param modifiers + * @param name + * @param parameterTypes + * @param returnType + * @param pointcut + */ + public ResolvedPointcutDefinition( TypeX declaringType, int modifiers, String name, TypeX[] parameterTypes, - Pointcut pointcut) + TypeX returnType, + Pointcut pointcut) { super( POINTCUT, declaringType, modifiers, - ResolvedTypeX.VOID, + returnType, name, parameterTypes); this.pointcut = pointcut; diff --git a/weaver/src/org/aspectj/weaver/bcel/AtAjAttributes.java b/weaver/src/org/aspectj/weaver/bcel/AtAjAttributes.java index 5de34cf38..938411661 100644 --- a/weaver/src/org/aspectj/weaver/bcel/AtAjAttributes.java +++ b/weaver/src/org/aspectj/weaver/bcel/AtAjAttributes.java @@ -847,9 +847,10 @@ public class AtAjAttributes { ElementNameValuePair pointcutExpr = getAnnotationElement(pointcut, VALUE); if (pointcutExpr != null) { - // semantic check: the method must return void - if (!Type.VOID.equals(struct.method.getReturnType())) { - reportWarning("Found @Pointcut on a method not returning void", struct); + // semantic check: the method must return void, or be "public static boolean" for if() support + if (!(Type.VOID.equals(struct.method.getReturnType()) + || (Type.BOOLEAN.equals(struct.method.getReturnType()) && struct.method.isStatic() && struct.method.isPublic()))) { + reportWarning("Found @Pointcut on a method not returning 'void' or not 'public static boolean'", struct); ;//no need to stop } // semantic check: the method must not throw anything @@ -888,6 +889,7 @@ public class AtAjAttributes { struct.method.getModifiers(), struct.method.getName(), argumentTypes, + TypeX.forSignature(struct.method.getReturnType().getSignature()), pc, binding ) @@ -1064,7 +1066,6 @@ public class AtAjAttributes { // } } - /** * Compute the flag for the xxxJoinPoint extra argument * @@ -1072,17 +1073,30 @@ public class AtAjAttributes { * @return */ private static int extractExtraArgument(Method method) { - int extraArgument = 0; Type[] methodArgs = method.getArgumentTypes(); + String[] sigs = new String[methodArgs.length]; for (int i = 0; i < methodArgs.length; i++) { - String methodArg = methodArgs[i].getSignature(); - if (AjcMemberMaker.TYPEX_JOINPOINT.getSignature().equals(methodArg)) { + sigs[i] = methodArgs[i].getSignature(); + } + return extractExtraArgument(sigs); + } + + /** + * Compute the flag for the xxxJoinPoint extra argument + * + * @param argumentSignatures + * @return + */ + public static int extractExtraArgument(String[] argumentSignatures) { + int extraArgument = 0; + for (int i = 0; i < argumentSignatures.length; i++) { + if (AjcMemberMaker.TYPEX_JOINPOINT.getSignature().equals(argumentSignatures[i])) { extraArgument |= Advice.ThisJoinPoint; - } else if (AjcMemberMaker.TYPEX_PROCEEDINGJOINPOINT.getSignature().equals(methodArg)) { + } else if (AjcMemberMaker.TYPEX_PROCEEDINGJOINPOINT.getSignature().equals(argumentSignatures[i])) { extraArgument |= Advice.ThisJoinPoint; - } else if (AjcMemberMaker.TYPEX_STATICJOINPOINT.getSignature().equals(methodArg)) { + } else if (AjcMemberMaker.TYPEX_STATICJOINPOINT.getSignature().equals(argumentSignatures[i])) { extraArgument |= Advice.ThisJoinPointStaticPart; - } else if (AjcMemberMaker.TYPEX_ENCLOSINGSTATICJOINPOINT.getSignature().equals(methodArg)) { + } else if (AjcMemberMaker.TYPEX_ENCLOSINGSTATICJOINPOINT.getSignature().equals(argumentSignatures[i])) { extraArgument |= Advice.ThisEnclosingJoinPointStaticPart; } } @@ -1231,9 +1245,10 @@ public class AtAjAttributes { private Pointcut m_lazyPointcut = null; - public LazyResolvedPointcutDefinition(ResolvedTypeX declaringType, int modifiers, String name, TypeX[] parameterTypes, + public LazyResolvedPointcutDefinition(ResolvedTypeX declaringType, int modifiers, String name, + TypeX[] parameterTypes, TypeX returnType, Pointcut pointcut, IScope binding) { - super(declaringType, modifiers, name, parameterTypes, null); + super(declaringType, modifiers, name, parameterTypes, returnType, null); m_pointcutUnresolved = pointcut; m_binding = binding; } @@ -1328,7 +1343,7 @@ public class AtAjAttributes { */ private static Pointcut parsePointcut(String pointcutString, AjAttributeStruct location) { try { - Pointcut pointcut = Pointcut.fromString(pointcutString); + Pointcut pointcut = new PatternParser(pointcutString, location.context).parsePointcut(); pointcut.setLocation(location.context, -1, -1);//FIXME -1,-1 is not good enough return pointcut; } catch (ParserException e) { diff --git a/weaver/src/org/aspectj/weaver/patterns/ExposedState.java b/weaver/src/org/aspectj/weaver/patterns/ExposedState.java index e76be017b..03dd40e15 100644 --- a/weaver/src/org/aspectj/weaver/patterns/ExposedState.java +++ b/weaver/src/org/aspectj/weaver/patterns/ExposedState.java @@ -46,7 +46,7 @@ public class ExposedState { //XXX add sanity checks // Some checks added in ArgsPointcut and ThisOrTargetPointcut // if (vars[i]!=null) { -// if (!var.getType().equals(vars[i].getType())) +// if (!var.getType().equals(vars[i].getType())) // throw new RuntimeException("Shouldn't allow a slot to change type! Currently="+var.getType()+" New="+vars[i].getType()); // } vars[i] = var; diff --git a/weaver/src/org/aspectj/weaver/patterns/IfPointcut.java b/weaver/src/org/aspectj/weaver/patterns/IfPointcut.java index 9a716e6e6..dc3ffc576 100644 --- a/weaver/src/org/aspectj/weaver/patterns/IfPointcut.java +++ b/weaver/src/org/aspectj/weaver/patterns/IfPointcut.java @@ -1,16 +1,15 @@ /* ******************************************************************* * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC). - * All rights reserved. - * This program and the accompanying materials are made available - * under the terms of the Common Public License v1.0 - * which accompanies this distribution and is available at - * http://www.eclipse.org/legal/cpl-v10.html - * - * Contributors: - * PARC initial implementation + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Common Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * PARC initial implementation + * Alexandre Vasseur if() implementation for @AJ style * ******************************************************************/ - - package org.aspectj.weaver.patterns; import java.io.DataOutputStream; @@ -34,28 +33,45 @@ import org.aspectj.weaver.Shadow; import org.aspectj.weaver.ShadowMunger; import org.aspectj.weaver.VersionedDataInputStream; import org.aspectj.weaver.WeaverMessages; +import org.aspectj.weaver.TypeX; +import org.aspectj.weaver.AjcMemberMaker; +import org.aspectj.weaver.bcel.AtAjAttributes; import org.aspectj.weaver.ast.Expr; import org.aspectj.weaver.ast.Literal; import org.aspectj.weaver.ast.Test; import org.aspectj.weaver.ast.Var; - public class IfPointcut extends Pointcut { public ResolvedMember testMethod; public int extraParameterFlags; - + + /** + * A token source dump that looks like a pointcut (but is NOT parseable at all - just here to help debugging etc) + */ + private String enclosingPointcutHint; + public Pointcut residueSource; int baseArgsCount; //XXX some way to compute args - public IfPointcut(ResolvedMember testMethod, int extraParameterFlags) { this.testMethod = testMethod; this.extraParameterFlags = extraParameterFlags; this.pointcutKind = IF; + this.enclosingPointcutHint = null; } - + + /** + * No-arg constructor for @AJ style, where the if() body is actually the @Pointcut annotated method + */ + public IfPointcut(String enclosingPointcutHint) { + this.pointcutKind = IF; + this.enclosingPointcutHint = enclosingPointcutHint; + this.testMethod = null;// resolved during concretize + this.extraParameterFlags = -1;//allows to keep track of the @Aj style + } + public Set couldMatchKinds() { return Shadow.ALL_SHADOW_KINDS; } @@ -122,19 +138,24 @@ public class IfPointcut extends Pointcut { IfPointcut o = (IfPointcut)other; return o.testMethod.equals(this.testMethod); } + public int hashCode() { int result = 17; result = 37*result + testMethod.hashCode(); return result; } - public String toString() { - return "if(" + testMethod + ")"; - } + public String toString() { + if (extraParameterFlags < 0) { + //@AJ style + return "if()"; + } else { + return "if(" + testMethod + ")";//FIXME AV - bad, this makes it unparsable. Perhaps we can use if() for code style behind the scene! + } + } //??? The implementation of name binding and type checking in if PCDs is very convoluted // There has to be a better way... - private boolean findingResidue = false; // Similar to lastMatchedShadowId - but only for if PCDs. @@ -155,43 +176,68 @@ public class IfPointcut extends Pointcut { Test ret = Literal.TRUE; List args = new ArrayList(); - // If there are no args to sort out, don't bother with the recursive call - if (baseArgsCount > 0) { - ExposedState myState = new ExposedState(baseArgsCount); - //??? we throw out the test that comes from this walk. All we want here - // is bindings for the arguments - residueSource.findResidue(shadow, myState); - - - for (int i=0; i < baseArgsCount; i++) { - Var v = myState.get(i); - args.add(v); - ret = Test.makeAnd(ret, - Test.makeInstanceof(v, - testMethod.getParameterTypes()[i].resolve(shadow.getIWorld()))); - } - } - - // handle thisJoinPoint parameters - if ((extraParameterFlags & Advice.ThisJoinPoint) != 0) { - args.add(shadow.getThisJoinPointVar()); - } - - if ((extraParameterFlags & Advice.ThisJoinPointStaticPart) != 0) { - args.add(shadow.getThisJoinPointStaticPartVar()); - } - - if ((extraParameterFlags & Advice.ThisEnclosingJoinPointStaticPart) != 0) { - args.add(shadow.getThisEnclosingJoinPointStaticPartVar()); - } - + // code style + if (extraParameterFlags >= 0) { + // If there are no args to sort out, don't bother with the recursive call + if (baseArgsCount > 0) { + ExposedState myState = new ExposedState(baseArgsCount); + //??? we throw out the test that comes from this walk. All we want here + // is bindings for the arguments + residueSource.findResidue(shadow, myState); + + + for (int i=0; i < baseArgsCount; i++) { + Var v = myState.get(i); + args.add(v); + ret = Test.makeAnd(ret, + Test.makeInstanceof(v, + testMethod.getParameterTypes()[i].resolve(shadow.getIWorld()))); + } + } + + // handle thisJoinPoint parameters + if ((extraParameterFlags & Advice.ThisJoinPoint) != 0) { + args.add(shadow.getThisJoinPointVar()); + } + + if ((extraParameterFlags & Advice.ThisJoinPointStaticPart) != 0) { + args.add(shadow.getThisJoinPointStaticPartVar()); + } + + if ((extraParameterFlags & Advice.ThisEnclosingJoinPointStaticPart) != 0) { + args.add(shadow.getThisEnclosingJoinPointStaticPartVar()); + } + } else { + // @style is slightly different + int currentStateIndex = 0; + //FIXME AV - "args(jp)" test(jp, thejp) will fail here + for (int i = 0; i < testMethod.getParameterTypes().length; i++) { + String argSignature = testMethod.getParameterTypes()[i].getSignature(); + if (AjcMemberMaker.TYPEX_JOINPOINT.getSignature().equals(argSignature)) { + args.add(shadow.getThisJoinPointVar()); + } else if (AjcMemberMaker.TYPEX_PROCEEDINGJOINPOINT.getSignature().equals(argSignature)) { + args.add(shadow.getThisJoinPointVar()); + } else if (AjcMemberMaker.TYPEX_STATICJOINPOINT.getSignature().equals(argSignature)) { + args.add(shadow.getThisJoinPointStaticPartVar()); + } else if (AjcMemberMaker.TYPEX_ENCLOSINGSTATICJOINPOINT.getSignature().equals(argSignature)) { + args.add(shadow.getThisEnclosingJoinPointStaticPartVar()); + } else { + // we don't use i as JoinPoint.* can be anywhere in the signature in @style + Var v = state.get(currentStateIndex++); + args.add(v); + ret = Test.makeAnd(ret, + Test.makeInstanceof(v, + testMethod.getParameterTypes()[i].resolve(shadow.getIWorld()))); + } + } + } + ret = Test.makeAnd(ret, Test.makeCall(testMethod, (Expr[])args.toArray(new Expr[args.size()]))); // Remember... ifLastMatchedShadowId = shadow.shadowId; ifLastMatchedShadowResidue = ret; return ret; - } finally { findingResidue = false; } @@ -221,14 +267,56 @@ public class IfPointcut extends Pointcut { null); return Pointcut.makeMatchesNothing(Pointcut.CONCRETE); } - + if (partiallyConcretized != null) { return partiallyConcretized; } - IfPointcut ret = new IfPointcut(testMethod, extraParameterFlags); - ret.copyLocationFrom(this); - partiallyConcretized = ret; - + + final IfPointcut ret; + if (extraParameterFlags < 0 && testMethod == null) { + // @AJ style, we need to find the testMethod in the aspect defining the "if()" enclosing pointcut + ResolvedPointcutDefinition def = bindings.peekEnclosingDefinitition(); + if (def != null) { + ResolvedTypeX aspect = inAspect.getWorld().resolve(def.getDeclaringType()); + ResolvedMember[] methods = aspect.getDeclaredJavaMethods(); + for (int i = 0; i < methods.length; i++) { + ResolvedMember method = methods[i]; + if (def.getName().equals(method.getName()) + && def.getParameterTypes().length == method.getParameterTypes().length) { + boolean sameSig = true; + for (int j = 0; j < method.getParameterTypes().length; j++) { + TypeX argJ = method.getParameterTypes()[j]; + if (!argJ.equals(def.getParameterTypes()[j])) { + sameSig = false; + break; + } + } + if (sameSig) { + testMethod = method; + break; + } + } + } + if (testMethod == null) { + inAspect.getWorld().showMessage( + IMessage.ERROR, + "Cannot find if() body from '" + def.toString() + "' for '" + enclosingPointcutHint + "'", + this.getSourceLocation(), + null + ); + return Pointcut.makeMatchesNothing(Pointcut.CONCRETE); + } + } else { + testMethod = inAspect.getWorld().resolve(bindings.getAdviceSignature()); + } + ret = new IfPointcut(enclosingPointcutHint); + ret.testMethod = testMethod; + } else { + ret = new IfPointcut(testMethod, extraParameterFlags); + } + ret.copyLocationFrom(this); + partiallyConcretized = ret; + // It is possible to directly code your pointcut expression in a per clause // rather than defining a pointcut declaration and referencing it in your // per clause. If you do this, we have problems (bug #62458). For now, @@ -260,7 +348,24 @@ public class IfPointcut extends Pointcut { return Pointcut.makeMatchesNothing(Pointcut.CONCRETE); } ret.baseArgsCount = def.getParameterTypes().length; - + + // for @style, we have implicit binding for JoinPoint.* things + //FIXME AV - will lead to failure for "args(jp)" test(jp, thejp) / see args() implementation + if (ret.extraParameterFlags < 0) { + ret.baseArgsCount = 0; + for (int i = 0; i < testMethod.getParameterTypes().length; i++) { + String argSignature = testMethod.getParameterTypes()[i].getSignature(); + if (AjcMemberMaker.TYPEX_JOINPOINT.getSignature().equals(argSignature) + || AjcMemberMaker.TYPEX_PROCEEDINGJOINPOINT.getSignature().equals(argSignature) + || AjcMemberMaker.TYPEX_STATICJOINPOINT.getSignature().equals(argSignature) + || AjcMemberMaker.TYPEX_ENCLOSINGSTATICJOINPOINT.getSignature().equals(argSignature)) { + ; + } else { + ret.baseArgsCount++; + } + } + } + IntMap newBindings = IntMap.idMap(ret.baseArgsCount); newBindings.copyContext(bindings); ret.residueSource = def.getPointcut().concretize(inAspect, newBindings); @@ -281,10 +386,11 @@ public class IfPointcut extends Pointcut { return visitor.visit(this, data); } - private static class IfFalsePointcut extends IfPointcut { + public static class IfFalsePointcut extends IfPointcut { public IfFalsePointcut() { super(null,0); + this.pointcutKind = Pointcut.IF_FALSE; } public Set couldMatchKinds() { @@ -355,10 +461,11 @@ public class IfPointcut extends Pointcut { return ret; } - private static class IfTruePointcut extends IfPointcut { + public static class IfTruePointcut extends IfPointcut { public IfTruePointcut() { super(null,0); + this.pointcutKind = Pointcut.IF_TRUE; } public boolean alwaysTrue() { diff --git a/weaver/src/org/aspectj/weaver/patterns/PatternParser.java b/weaver/src/org/aspectj/weaver/patterns/PatternParser.java index 32ff9d1a9..d63484e0f 100644 --- a/weaver/src/org/aspectj/weaver/patterns/PatternParser.java +++ b/weaver/src/org/aspectj/weaver/patterns/PatternParser.java @@ -317,6 +317,33 @@ public class PatternParser { SignaturePattern sig = parseConstructorSignaturePattern(); eat(")"); return new KindedPointcut(Shadow.PreInitialization, sig); + } else if (kind.equals("if")) { + //@style support + parseIdentifier(); + eat("("); + if (maybeEat("true")) { + eat(")"); + return new IfPointcut.IfTruePointcut(); + } else if (maybeEat("false")) { + eat(")"); + return new IfPointcut.IfFalsePointcut(); + } else { + //TODO AV - true/false stuff needed ? What are the token here ? + eat(")"); + // build a readable pointcut as an hint (toString() dumps raw token array into an horrible thing) + StringBuffer sb = new StringBuffer(); + int currentIndex = tokenSource.getIndex(); + try { + tokenSource.setIndex(0); + for (int i = 0; !IToken.EOF.equals(tokenSource.peek(i)); i++) { + if (i > 0) sb.append(' '); + sb.append(tokenSource.peek(i).getString()); + } + } finally { + tokenSource.setIndex(currentIndex); + } + return new IfPointcut(sb.toString()); + } } else { return parseReferencePointcut(); } @@ -770,9 +797,9 @@ public class PatternParser { if (previous != null) { if (!isAdjacent(previous, tok)) break; } - if (tok.getString() == "*" || (tok.isIdentifier() && tok.getString()!="...")) { + if ("*".equals(tok.getString()) || (tok.isIdentifier() && !"...".equals(tok.getString()))) { buf.append(tok.getString()); - } else if (tok.getString()=="...") { + } else if ("...".equals(tok.getString())) { break; } else if (tok.getLiteralKind() != null) { //System.err.println("literal kind: " + tok.getString()); @@ -842,7 +869,7 @@ public class PatternParser { if (previous != null) { if (!isAdjacent(previous, tok)) break; } - if (tok.getString() == "*" || tok.isIdentifier()) { + if (tok.getString().equals("*") || tok.isIdentifier()) { buf.append(tok.getString()); } else if (tok.getLiteralKind() != null) { //System.err.println("literal kind: " + tok.getString()); @@ -1103,7 +1130,7 @@ public class PatternParser { public String parseStringLiteral() { IToken token = tokenSource.next(); String literalKind = token.getLiteralKind(); - if (literalKind == "string") { + if (literalKind.equals("string")) { return token.getString(); } @@ -1142,7 +1169,7 @@ public class PatternParser { public boolean maybeEat(String token) { IToken next = tokenSource.peek(); - if (next.getString() == token) { + if (next.getString().equals(token)) { tokenSource.next(); return true; } else { @@ -1162,7 +1189,7 @@ public class PatternParser { public boolean peek(String token) { IToken next = tokenSource.peek(); - return next.getString() == token; + return next.getString().equals(token); } diff --git a/weaver/src/org/aspectj/weaver/patterns/PerThisOrTargetPointcutVisitor.java b/weaver/src/org/aspectj/weaver/patterns/PerThisOrTargetPointcutVisitor.java index 54eead76c..6eb953e7e 100644 --- a/weaver/src/org/aspectj/weaver/patterns/PerThisOrTargetPointcutVisitor.java +++ b/weaver/src/org/aspectj/weaver/patterns/PerThisOrTargetPointcutVisitor.java @@ -11,11 +11,9 @@ *******************************************************************************/ package org.aspectj.weaver.patterns; -import org.aspectj.weaver.Member; import org.aspectj.weaver.Shadow; import org.aspectj.weaver.ResolvedPointcutDefinition; import org.aspectj.weaver.ResolvedTypeX; -import org.aspectj.weaver.World; /** * A visitor that turns a pointcut into a type pattern equivalent for a perthis or pertarget matching: diff --git a/weaver/src/org/aspectj/weaver/patterns/PointcutVisitor.java b/weaver/src/org/aspectj/weaver/patterns/PointcutVisitor.java index 6f2acffd0..1abf102ff 100644 --- a/weaver/src/org/aspectj/weaver/patterns/PointcutVisitor.java +++ b/weaver/src/org/aspectj/weaver/patterns/PointcutVisitor.java @@ -610,11 +610,13 @@ public interface PointcutVisitor { public static void main(String args[]) throws Throwable { String[] s = new String[]{ - //"@args(Foo, Goo, *, .., Moo)", - //"execution(* *())", - //"call(* *(int, Integer...))", - //"staticinitialization(@(Foo) @(Boo) @(Goo) Moo)", - "staticinitialization(!@(Immutable) *)" +// "@args(Foo, Goo, *, .., Moo)", +// "execution(* *())", +// "call(* *(int, Integer...))", +// "staticinitialization(@(Foo) @(Boo) @(Goo) Moo)", +// "staticinitialization(!@(Immutable) *)" +// "execution(* *()) && if()", + "(if(true) && set(int BaseApp.i))" }; for (int i = 0; i < s.length; i++) { diff --git a/weaver/src/org/aspectj/weaver/tools/PointcutParser.java b/weaver/src/org/aspectj/weaver/tools/PointcutParser.java index 949165053..f1f12af67 100644 --- a/weaver/src/org/aspectj/weaver/tools/PointcutParser.java +++ b/weaver/src/org/aspectj/weaver/tools/PointcutParser.java @@ -24,6 +24,7 @@ import org.aspectj.weaver.patterns.ParserException; import org.aspectj.weaver.patterns.PatternParser; import org.aspectj.weaver.patterns.Pointcut; import org.aspectj.weaver.patterns.ThisOrTargetPointcut; +import org.aspectj.weaver.patterns.IfPointcut; /** * A PointcutParser can be used to build PointcutExpressions for a @@ -142,9 +143,13 @@ public class PointcutParser { throw new UnsupportedOperationException("handler is not supported by this parser"); break; case Pointcut.IF: + if (((IfPointcut)pc).extraParameterFlags >= 0) { + throw new UnsupportedOperationException("if not supported for non @AspectJ style"); + } + break; case Pointcut.IF_FALSE: case Pointcut.IF_TRUE: - throw new UnsupportedOperationException("if is not supported by this parser"); + break; case Pointcut.KINDED: validateKindedPointcut(((KindedPointcut)pc)); break; diff --git a/weaver/testdata/visitor.pointcuts.txt b/weaver/testdata/visitor.pointcuts.txt index f75db3d5c..17e4a7d9f 100644 --- a/weaver/testdata/visitor.pointcuts.txt +++ b/weaver/testdata/visitor.pointcuts.txt @@ -2340,3 +2340,60 @@ this(i) target(foo) set(Integer *) call(* System.*(..)) +(args(x) && if()) +(execution(void IfPcd.main(..)) && if()) +if() +(args(o) && if()) +(if() && execution(* LazyTjp.doit(..))) +(if() && execution(* LazyTjp.doit2(..))) +(if() && execution(* LazyTjp.doit3(..))) +if(true) +(execution(* doCommand(..)) && if()) +if(false) +(within(IfFalse) && if(false)) +!if(true) +(!if() && execution(* *(..))) +(within(IfTrue) && !if(true)) +(execution(void m2()) && if()) +(execution(void main(..)) && !if()) +(execution(void main(..)) && if()) +(execution(void main(String)) && (!if() && args(a))) +call(* ThisJoinPointAndVerifier.*(..)) +(if() && (lexicalScope() && !within(Trace+))) +serverIdentification(FTPServer) +(checkedCut() && if()) +(if() && if()) +(if() && (if() && call(void IfPCDExprJoinPointVisibleCE.main(..)))) +(if() && (if() && callMain(args))) +ifFalse(Object) +(this(t) && if()) +(!within(Aspect) && if()) +(if(true) && set(int BaseApp.i)) +(if(true) && get(int BaseApp.i)) +(if(true) && (call(void *.call(int)) && within(BaseApp))) +(if(true) && call(void BaseApp.call(int))) +(if(true) && (within(BaseApp) && execution(void *(int)))) +(if(true) && initialization(BaseApp.new(..))) +(if(true) && call(void *.uncountedCall())) +(if(true) && call(void BaseApp.uncountedCall())) +(if(true) && execution(void BaseApp.uncountedCall())) +(if() && (!within(A) && (!call(* A.*(..)) && (!initialization(new(..)) && !preinitialization(new(..)))))) +(hasEnclosingJoinPoint() && enclosingDiffers()) +!enclosingDiffers() +(hasEnclosingJoinPoint() && !enclosingDiffers()) +hasDifferentEnclosingJoinPoint() +(execution(static String PR590.staticMethod()) && if()) +(args(i) && (if() && safety())) +(safety() && if()) +(if() && get(int AroundCasting.x)) +(call(String C.doit(Object)) && if()) +(execution(String C.doit(Object)) && if()) +(p() && if()) +(if() && (call(void C.foo(C)) && args(d))) +(execution(* Test.a(..)) && if()) +set(@(Persisted) @(Classified) * *) +(call(* *(..)) && @target(Classified)) +(call(* *(..)) && @target(classificationInfo)) +callToClassifiedObject(classification) +@args(Classified, ..) +classifiedArgument() diff --git a/weaver/testsrc/org/aspectj/weaver/tools/PointcutParserTest.java b/weaver/testsrc/org/aspectj/weaver/tools/PointcutParserTest.java index aea55aaf3..b5f442a03 100644 --- a/weaver/testsrc/org/aspectj/weaver/tools/PointcutParserTest.java +++ b/weaver/testsrc/org/aspectj/weaver/tools/PointcutParserTest.java @@ -65,10 +65,12 @@ public class PointcutParserTest extends TestCase { public void testParseIfPCD() { PointcutParser p = new PointcutParser(); try { + // AV - those 3 are supported for @style p.parsePointcutExpression("if(true)"); - fail("Expected UnsupportedOperationException"); - } catch(UnsupportedOperationException ex) { - assertTrue(ex.getMessage().startsWith("if pointcuts and reference pointcuts are not supported")); + p.parsePointcutExpression("if(true)"); + p.parsePointcutExpression("if()"); + } catch(Throwable t) { + fail(t.toString()); } } -- 2.39.5