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

Both modifiers and categories sound very useful and not confusing.

Here's a (non-exclusive) syntax alternative: type({specifiers})

Currently we have type, typepattern, methodpattern, constructorpattern,
and of course pointcut.  Only pointcut can be named, but developers
have asked for others to also be named, composible, and parameterized
-- which points to function syntax.  To emphasize that they are resolved
at compile-time and to simplify parsing, any naming could/should use
the declare prefix.  That gives us a nice default path for extending
these forms (indeed, we might update pointcut to support that syntax).
So even if we decide to support position-based syntax, e.g.,

   execution( (public *) *(..))

We could also support the function form:

   execution( type(public *) *(..))

and we could restrict certain specifiers to the function form
if they didn't work in the native form.  So:

  //---- 1.2
  after () throwing (AppException || ConnectException) : ...
  after () throwing type(AppException || ConnectException) : ...

  declare unsupportedExceptions() :
      !type(AppException || ConnectException);

  after () throwing unsupportedExceptions() : ...

  declare guiconnectors() :
      type((@inner || @anonymous) && Action+);

  before() : logging() && !within(type(@aspect)) : { ... }

  declare warning : staticinitialization(guiconnectors())
      && within(com.mycompany..*) : "...";

  //---- 1.3 ?
  declare innerOf(<Foo>) : type(@inner && <Foo>+);

Advantages:

- The function syntax reinforces rather than hides the base syntax
(though if naming is supported, developers can declare confusing names)

- A given function context/namespace might disambiguate special forms:

      type(@aspect && @inner)

- Old forms can still be supported, but there's also an easy
path for programmatically upgrading them to the new forms

- As the language advances, the effects are contained within
a given function.  It might make it easier to add new features
or to support pluggable language extensions.  It's easy to
decide and document a given form:
  - accepted specifiers?
  - composible?
  - nameable?
  - parameterized?


But here's some counter-examples:

  before(): call(type(public) type(public).foo(..)) { ... }

  declare targetTypes() : type(...);

  before(): call(void targetTypes().foo(..)) { ... }

When comparing syntax for usability, I'd like to see examples both
small and large, and using possibly-complex composition.  I think
the function syntax might seem slightly verbose for the small
examples (except where old forms are permitted), but much clearer
for large or complex examples, and much easier to learn.  The
pointcut syntax is probably the biggest mental/visual block to
learning AspectJ, and using function syntax might reduce that.

Wes

Jim Hugunin wrote:

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




Back to the top