Bug 100385 - support for matching of subclasses of annotated classes
Summary: support for matching of subclasses of annotated classes
Status: RESOLVED FIXED
Alias: None
Product: AspectJ
Classification: Tools
Component: Compiler (show other bugs)
Version: unspecified   Edit
Hardware: PC Windows XP
: P3 enhancement (vote)
Target Milestone: ---   Edit
Assignee: Adrian Colyer CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2005-06-16 08:38 EDT by Grzegorz Glowaty CLA
Modified: 2005-08-17 15:27 EDT (History)
0 users

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Grzegorz Glowaty CLA 2005-06-16 08:38:45 EDT
I have two classes, Foo and Bar
@Ann class Foo {
}

Bar extends Foo {
}

I would like to have a way to match all subclasses of any class annotated with
annotation @Ann. Currently I can easily match Foo, with @Ann * * *.*(..) but I
cannot match Bar (unless it is explicitelly annotated with @Ann)

The same could applly to methods, e.g. matching of all the methods wich override
a method annotated with some annotation.
Comment 1 Andrew Clement CLA 2005-06-16 09:13:19 EDT
This is down to standard annotation inheritance rules for Java.  By default they
aren't inherited, if you mark your @Ann as being @Inherited then Bar will also
have the annotation.

This program demonstrates inheritance:
---
import java.lang.annotation.*;

@Inherited
@interface Blue {}

@Blue class A {
}

class T extends A {
}

aspect X {
  before(): staticinitialization(@Blue *) {
  }
}
---

C:\aspectj1.5.0-dev>ajc -showWeaveInfo -1.5 B.aj
Type 'A' (B.aj:6) advised by before advice from 'X' (B.aj:13)

Type 'T' (B.aj:9) advised by before advice from 'X' (B.aj:13)


Note, inheritance *only* works for types, it will not work for methods - that is
what the Java spec defines.  For more discussion, see:

http://eclipse.org/aspectj/doc/next/adk15notebook/annotations.html#d0e694
Comment 2 Grzegorz Glowaty CLA 2005-06-16 09:15:43 EDT
Yes, I'm sorry I forgot about @Inherited annotation. But as you said it works
for class level annotations only, is there any way to match all methods which
override some annotated method? Any AspectJ syntax?
Comment 3 Andrew Clement CLA 2005-06-16 09:25:10 EDT
I can't think of a way - there is no new AspectJ syntax to do it.  I think its a
deficiency in the java rules for @Inherited...  maybe you can do something with
APT to propagate the annotations down to overloaded methods, and then run AspectJ.
Comment 4 Grzegorz Glowaty CLA 2005-06-16 09:28:08 EDT
Yes, apt is an option but currently I avoid using it and I would prefer to.
Anyways thank you for clarification.
Comment 5 Alexandre Vasseur CLA 2005-06-16 09:37:06 EDT
You cannot use APT since APT does not allow to modify input artifact. You could
only produce an output file or sort of, but then AspectJ weaver would ignore it.

One way would be to generate an aspect with a sort of a declare annotation.

Isn't there a way to write / support the following in the type pattern parser /
matching mechanism:

(@Ann *)+

ie all subclass(or implementation) of type annotated with @Ann

so that:

"within((@Ann *)+)" would solve this issue.
(this at the cost of unpacking all class level annotation etc etc off course).

Comment 6 Andrew Clement CLA 2005-06-16 09:55:53 EDT
> You cannot use APT since APT does not allow to modify input artifact. 
> You could only produce an output file or sort of, but then AspectJ 
> weaver would ignore it.

I thought APT was a source-to-source transformer?  I was merely thinking a
simple APT run over the code could copy annotations down from method to
overridden methods completely standalone *before* AspectJ is run ?? Will that
not work??

I suppose we could support (@Ann *)+ - but since @Inherited solves the problem
for types...
Comment 7 Grzegorz Glowaty CLA 2005-06-16 09:58:35 EDT
It solves problem for types but doesn't solve problem for implemented interfaces.
From @Inherited documentation:

"Note that this meta-annotation type has no effect if the annotated type is used
to annotate anything other than a class. Note also that this meta-annotation
only causes annotations to be inherited from superclasses; annotations on
implemented interfaces have no effect."
Comment 8 Alexandre Vasseur CLA 2005-06-16 10:28:15 EDT
APT as it is now is very limited.
It cannot alter its soruce. It's power comes from its cyclic behavior: if you
generate a source with annotation, then this new one will be injected again as
an input and so on (hence f.e. a POJO can generate an EJB 3 that can then
generate a descriptor etc etc), and from its mirror API (exposes types ala
java.lang.reflect somehow no matter if they come from binary dependancies or
source artifact beeing build or just produced etc)

But APT does not let you change the input, and neither replicate it since it
does not even exposes the bodies of the methods or static{} blocks (JDT does
that somehow..)
Other JSR have surfaced for that
- one to extract APT from the com.sun.* packages first to have it in java.*
something, among other things
- one to provide javac compiler extension



So I guess we would need a feature request to support more complex type pattern
- including in return type and parameter types.
For now an if() pointcut and some reflective test can perhaps do it ?
Comment 9 Adrian Colyer CLA 2005-08-17 15:27:26 EDT
The type pattern (@Ann *)+ matches any type with the @Ann annotation or any subtype thereof. There was 
a parser bug related to this pattern until recently, but that is fixed in the current development builds of 
AspectJ available from the download page.