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

This message is about what support for annotations in AspectJ might look
like.  We should spend a little time on this discussion because it is
surprisingly coupled to extending TypePatterns to include modifiers.

Adrian Colyer wrote:
> JSR 175 basically says that annotations can occur on any declaration:
<snip>

JSR 175 also says that "an annotation is a new kind of modifier...
Annotations are conventionally placed before all other modifiers, but this
is not a requirement; they may be freely intermixed with other modifiers."

This rule puts a lot of pressure on us to allow annotations to be used in
any ModifierPattern.  JSR 175 lets me write the following method
declaration:
  public @TxRequired void updateAccount() { ... }

I'd expect to be able to write the corresponding pointcut:
  execution(public @TxRequired void updateAccount())


Here are what your examples would look like if we extend ModifiersPat to
include attributes and at the same type allow a ModifiersPat to be added to
a TypePat.  I think that these examples show that extending ModifiersPat
doesn't interfere with the ability to manage complex expressions.

> target(@AttributeOne)
target(@AttributeOne *) -- and we could make the * optional

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

call(* *(..)) && target(@AttributeOne @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();

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

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

call(* *(..)) && (target(Foo) || attrOneAndTwo());

> 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.

I think it would be dangerously non-orthogonal to extend ModifiersPat for
MethodPat, ConstructorPat and FieldPat to include attribute patterns, but
not to do the same for TypePat.  This would also prevent us from specifying
some interesting things, i.e.
  execution( (private *) *(..)) - all methods that return a private type

> 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)

I'd like to point out that this example isn't any less confusing if you
replace the attributes with subtype checks which you can do today, i.e.
execution(public (SessionBean+ || EntityBean+)
          (com.myco..* && BusinessDomain+).*(..,@SensitiveData)
          throws Auditable+)


Wes Isberg wrote:
> 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?

This is a good set of examples.  The good news is that the compiler/weaver
can and will be able to detect these kinds of mistakes.  The attribute spec
includes tags for attributes to specify what kinds of declarations they can
be applied to.  So long as the user has correctly specified the
@TransactionRequired attribute to only be allowed on methods then the
compiler/weaver will be able to signal an error in the case you show.

-Jim




Back to the top