Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [aspectj-users] Language: support for modifiers in TypePatterns


JSR 175 basically says that annotations can occur on any declaration: class, interface, field, method, parameter, constructor, enum, enum constant, local variable, and package declaration. (To which list we could consider adding in time: declare, pointcut, advice, aspect, itd - topic of another thread!).

Let's rule out local variables from the discussion.

As Wes points out, there are two dimensions to consider: the compile-time type of something, and the actual run-time type. I like to think of attributes as "context" information at a join point. If we work with just run-time types for the moment, then args, this and target all logically acquire an attribute-matching variant:

target(@AttributeOne)
this(@AttributeTwo)
args(..,@AttributeThree)

I'm currently leaning towards a grammar like this:

target ::= target(Type | Var | Attribute)

rather than consuming the Attribute into the Type specifier.

In other words we can write:

// target must be of type Foo, with both attr one and attr two
call(* *(..)) && target(Foo) && target(@AttributeOne) && target(@AttributeTwo)    

rather than:
call(* *(..)) && target((@AttributeOne && @AttributeTwo) Foo)
(or if attribute patterns are forbidden here: target(@AttributeOne Foo) && target(@AttributeTwo Foo) ).

the former style gives us more flexibility to manage complex expressions, e.g.

pointcut attrOneAndTwo() : target(@AttributeOne) && target(@AttributeTwo);
call(* *(..)) && target(Foo) && attrOneAndTwo();

It also lets us write:
call(* *(..)) && (target(Foo) || attrOneAndTwo());

which I prefer to:
call(* *(..)) && (target(Foo) || (target((@AttributeOne && @AttributeTwo) Object))))


For compile-time (static) matching, we currently define MethodPat, ConstructorPat, and FieldPat as

[ModifiersPat] TypePat [TypePat . ] IdPat (TypePat, ... )
[ModifiersPat] TypePat . ] new (TypePat , ... )
[ModifiersPat] TypePat [TypePat.]IdPat

respectively.

It seems straight-forward and unambiguous (as Wes suggests) to extend the ModifiersPat to contain attribute patterns, and these would refer to the method, constructor, or field declaration as appropriate.

Where the examples we've looked at so far start to get confusing (to my eye), is when TypePat is extended to allow attribute patterns also. Try the following execution example on for size:

execution((@TxRequired || @TxMandatory) public (@SessionBean || @EntityBean) (com.myco..* && @BusinessDomain).*(..,@SensitiveData) throws @Auditable)

(execution of a public method requiring a transaction, on a business domain object in the com.myco packages, returning an EJB. The method takes a parameter containing sensitive data, and throws an exception that should be audited).

The essence of the problem is that TypePat can occur in so many positions, and there's no mechanism to abstract one. Being able to name and compose type patterns might help. Another (radical) suggestion is to offer an alternate pointcut declaration style, based more on the form-filling approach:

--- warning : crazy scheme ahead... ---

pointcut prettyRareEvent() : execution (
    method-modifiers : (@TxRequired || @TxMandatory) public;
    return-type : @SessionBean || @EntityBean;
    defining-type:  com.myco..* && @BusinessDomain;
    method-name: *;
    parameters: (..,@SensitiveData);
    throws: @Auditable )

placeholder names could be omitted if that portion of the 'form' was unconstrained. The goal of this style of declaration is to combat the loss of positional information in the original style.

--- end of crazy scheme ---

And let's remember, all Jim was trying to do in the original problem statement was extend type pattern to add some new modifiers. The (perceived | real) complexity of the pointcut language is one of the things that people most seem to dislike about AspectJ (and AO languages in general) on first sight, so we need to tread very carefully when considering adding to its expressive power (but we *do* need to address attributes next year).

-- Adrian
Adrian_Colyer@xxxxxxxxxx



Wes Isberg <wes@xxxxxxxxxxxxxx>
Sent by: aspectj-users-admin@xxxxxxxxxxx

17/12/2003 08:18
Please respond to aspectj-users

       
        To:        aspectj-users@xxxxxxxxxxx
        cc:        
        Subject:        Re: [aspectj-users] Language: support for modifiers in TypePatterns



 > Whatever route we go, there still remains the ambiguity in some
situations
> of whether the qualification refers to *this* or *target*.
> e.g. call(@ClassType * *(..))    which is the @ClassType - this or
target?
> Probably target here... what if I wanted to specify *this*?

I don't see how it might refer to "this".  And it doesn't
refer to the target, but to the method.  E.g.,  in

  call(@TransactionRequired * *(..))

@TransactionRequired refers to the method-call join point signature,
which has the same signature as the method being called.
The attributes of the method's declaring class are not included
in the method signature, AFAIK.

To adopt Jim's rules for disambiguating access specifiers, in

  call((@ClassType *) *(..))

@ClassType refers to the return type of the method-call
join point.  Similarly,

  call(void (@ClassType *).*(..))

refers to the compile-time type of the invoking reference.

This

  target(@ClassType *)

refers to the run-time type of the target object, but

  call(@ClassType void *(..)) // err?

is a mistake since @ClassType is an attribute of types,
not methods.  Same result, converse reason, for

  call((@TransactionRequired *) *(..)) // err?

except that @TransactionRequired is an arbitrary user-
specified attribute, while @ClassType is one we specify
is to be used only for types (or to be otherwise
disambiguated via qualification).

Which raises the question: should we be able to detect
these mistakes?

If the compiler is ignorant of the semantics of @interface,
it can't detect the error.  That suggests using
isInterface(), but that seems to force composition:

 call(void (isInterface() && *)(..))   // err
 call(void (isInterface() && *).*(..)) // fix
 call(void (* && isInterface()).*(..)) // hmm

yuck!

Is function-syntax variant any clearer?

  call(void typepat(isInterface() && *)(..)) // err
  call(void typepat(isInterface() && *).*(..))

  call(void typepat(@interface *)(..)) // err
  call(void typepat(@interface *).*(..))

  //declare roletype() : typepat(isInterface() && (public com.foo..*));
  declare roletype() : typepat(@interface public com.foo..*);
  call(void roletype()()) // err
  call(void roletype().*()) // hmm

Wes

Adrian Colyer wrote:

>>Most of the matching rules we have for other declarations translate
>
> easily
>
>>to types.  There are two type-specific questions that must be answered:
>>1. Does "abstract *" match interfaces?  I think the answer is yes.
>
>
> My vote is for yes too.
>
>
>>2. Does "static *" match top-level types?  I think the answer is yes.
>
>
> Yes again.
>
>
>>Here are two sets of names in the attribute style:
>>@InterfaceType @ClassType @AspectType @InnerType @AnonymousType
>>@interface @class @aspect @inner @anonymous
>
>
>>Here are two sets of names in the sets style:
>>isInterface(), isClass(), isAspect(), isInner(), isAnonymous()
>>interface, class, aspect, inner, anonymous
>
>
> Like Ron, I find the isInterface() style easiest to read right now.
> However, knowing that the attribute style will be coming to the pointcut
> language very soon once J2SE 1.5 is out, and being wary of pushing too
> many new elements into the pointcut language, I think we should take a
> good hard look at the attribute style. If we can find a way to do this
> that will be compatible with the use of attribute-matching pointcut
> expressions in general then that has a strong appeal to me. Especially
> Jim's suggestion that the attributes could be defined in some package -
> can we take this to the point where there is nothing special about these
> particular attributes as compared to any others that we might wish to pick
> out in the future? Figuring this out of course means we need to have some
> discussion about the envisaged form of attribute-matching pointcut
> expressions in aspectj in general.
>
> Whatever route we go, there still remains the ambiguity in some situations
> of whether the qualification refers to *this* or *target*.
> e.g. call(@ClassType * *(..))    which is the @ClassType - this or target?
> Probably target here... what if I wanted to specify *this*?
> We'll either need a simple rule to handle this, or a way for the user to
> specify (or both).
>
> Like Wes, I like the notion of being able to name and compose
> (type|method|field|...) patterns. My instinct is that adding these to the
> language for 1.2 will be a tall order (unless we come up with a very
> simple and clear design - both in the language and implementation - and
> some compelling use cases), but our ultimate proposal for type patterns
> should hopefully not preclude us from going down that road in a future
> release should we want to.
>
> -- Adrian
> Adrian_Colyer@xxxxxxxxxx
>
>
>
>
> "Jim Hugunin" <lists@xxxxxxxxxxx>
> Sent by: aspectj-users-admin@xxxxxxxxxxx
> 16/12/2003 16:50
> Please respond to aspectj-users
>  
>         To:     <aspectj-users@xxxxxxxxxxx>
>         cc:
>         Subject:        [aspectj-users] Language: support for modifiers in
> TypePatterns
>
>
> Process note: This message is intended for BOTH aspectj users and
> developers.  I'm sending it to just the users list because I assume that
> all
> developers will be reading both lists and I dislike having two threads
> about
> the same topic.
>
>
> This is the first of several messages to explore potential new language
> features for AspectJ-1.2.
>
> The first proposed feature is to extend TypePattern to include modifiers
> in
> the same way that modifiers are currently allowed on method, field and
> constructor signature patterns.
>
> https://bugs.eclipse.org/bugs/show_bug.cgi?id=44365
>
> This example matches the static initialization of all public types:
>   pointcut publicInit(): staticinitialization(public *);
>
> Most of the matching rules we have for other declarations translate easily
> to types.  There are two type-specific questions that must be answered:
> 1. Does "abstract *" match interfaces?  I think the answer is yes.
> 2. Does "static *" match top-level types?  I think the answer is yes.
>
> There is one very annoying issue with syntax ambiguity.
>
> Consider "execution(public * *(..))", does this match all public methods
> or
> all methods whose return type is public?  This has to continue to match
> all
> public methods or this would be an incompatible change from AspectJ-1.1.
>
> If you want to match all methods whose return type is public you'd need to
> write, "execution( (public *) *(..))".  This is a reasonable resolution of
> the ambiguity, but all of those parentheses make me a little queasy.  I
> feel
> like I'm reading a C type declaration with too many embedded function
> pointers.
>
> I don't see any better solution to the syntax ambiguity than ()'s.  Using
> []'s would be worse because of confusion with array types.  Using <>'s
> would
> be equally bad when we add support for generics.
>
> <dangerous-proposal>
> C programmers solve this kind of problem by using typedefs to give a name
> to
> complicated type patterns like this.  Several people have made proposals
> in
> the past for a way to name type patterns.  We may wish to consider
> something
> like this:
>   declare typename: PublicFinalType: public final *;
>
> This is probably not needed enough to do for the 1.2 release but if we
> expand the complexity of the TypePattern syntax I'm certain that something
> like this will be demanded in 1.3.
> </dangerous-proposal>
> ----------------------------------------------
>
> To make TypePatterns more powerful (and unfortunately more complicated) we
> would also like to add the ability to match on categories of types.  I
> believe the set of useful categories is interface, class, aspect, inner,
> and
> anonymous.  The semantics of matching these categories is obvious.  The
> best
> syntax is less clear.
>
> I propose that we do this using the syntax that we expect to see for
> attributes in Java-1.5 from JSR-175.  Here's an example to match join
> points
> within the public CLASSES in a package:
>   within(@ClassType public com.boxes..*)
>
> Here are two sets of names in the attribute style:
> @InterfaceType @ClassType @AspectType @InnerType @AnonymousType
> @interface @class @aspect @inner @anonymous
>
> The first set of names look like actual attribute types.  If using them we
> may want to also require the import of some org.aspectj.lang package that
> would define them.  The second set of names could be thought of as
> reserved
> words.  Only the two names "inner" and "anonymous" would have danger of
> name
> collisions.
>
> Instead of treating these categories as modifiers, we could have some
> special type patterns that would match all members of a category and use
> &&,
> || and ! for combining them.  The previous example to match join points
> within the public classes in a package would look like:
>   within(isClass() && public com.boxes..*)
>
> Here are two sets of names in the sets style:
> isInterface(), isClass(), isAspect(), isInner(), isAnonymous()
> interface, class, aspect, inner, anonymous
>
>
> I believe that both modifiers and categories would be valuable additions
> to
> 1.2.  The semantics of this feature doesn't appear to have any
> difficulties.
> I'm less happy with the syntax.  My personal opinion is that all of the
> syntax variants in this message are tolerable, but none of them are great.
> However, it's also clear that this change does noticeably increase the
> complexity of AspectJ's already complex pointcut designator language.  We
> need to proceed cautiously here.
>
> -Jim
>
>
> _______________________________________________
> aspectj-users mailing list
> aspectj-users@xxxxxxxxxxx
> http://dev.eclipse.org/mailman/listinfo/aspectj-users
>
>

_______________________________________________
aspectj-users mailing list
aspectj-users@xxxxxxxxxxx
http://dev.eclipse.org/mailman/listinfo/aspectj-users


Back to the top