Bug 405016 - Add annotation value support for type java.lang.Class[]
Summary: Add annotation value support for type java.lang.Class[]
Status: NEW
Alias: None
Product: AspectJ
Classification: Tools
Component: Compiler (show other bugs)
Version: 1.7.2   Edit
Hardware: PC Mac OS X
: P3 normal (vote)
Target Milestone: ---   Edit
Assignee: aspectj inbox CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2013-04-05 11:58 EDT by Matthew Adams CLA
Modified: 2013-04-25 22:25 EDT (History)
1 user (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Matthew Adams CLA 2013-04-05 11:58:46 EDT
I'm getting the following compiler error:

Compiler limitation: annotation value support not implemented for type java.lang.Class[]

I need to write a type expression that matches when the values of a multivalued annotation property of type Class<?>[] include some subset of values.

My current requirement is to pick out just one of the values.

Example:
===== annotation
public @interface Gimme {
  Class<?>[] value;
}
===== class using annotation
@Gimme({ Cloneable.class, Serializable.class})
public class Thingy {
  // ...
}
===== aspect
// ...
declare parents: (@Gimme(value = Serializable.class) *) implements Serializable;
=====

Since these are classes, I would expect the polymorphic "+" operator to be supported as well.

Thinking further about the requirements, I realize that this issue could be two separate issues:  one addressing the type (Class[]), and one addressing the ordering semantics of Java arrays.

Since multivalued property types on annotations are always expressed as arrays ("[]" suffix), then ordering semantics would apply and should probably be supported.  I suppose a workable syntax would be to use "{" & "}" along with "..".

... (@Gimme(value = {..,Serializable.class,..}) *) ...

would be equivalent to my example above, but you could match on arbitrary ordering as well:

... (@Gimme(value = {*,Foo.class,..,(Bar+ || Florp).class,Goo.class,..}) *) ...

The above expression is looking for a @Gimme with one element followed by Foo.class, then zero or more elements, then an element compatible with Bar.class or exactly Florp.class, then a Goo.class, then zero or more elements; it would match 
@Gimme({Serializable.class,Foo.class,Hoo.class,SubBoo.class,Bar.class,Goo.class,Barf.class})

Perhaps, then, given the ordering facet of this issue, operator "=" should only be used with single-valued annotation properties and "{..,*}"-type syntax should be used with multivalued ones.

See http://aspectj.2085585.n4.nabble.com/Matching-on-one-of-an-annotation-s-values-in-a-multivalued-property-tp4650839.html for question that, along with compiler error above, prompted this issue.
Comment 1 Matthew Adams CLA 2013-04-22 15:18:15 EDT
WRT the "contains" semantics, did you decide on "=" v. "{}"?  That is, will "=" be overridden to mean "contains" in the case of testing for a single value?  (Discussed at http://aspectj.2085585.n4.nabble.com/Matching-on-one-of-an-annotation-s-values-in-a-multivalued-property-tp4650839p4650846.html)
Comment 2 Matthew Adams CLA 2013-04-22 15:19:24 EDT
Also, are you intending to deliver this with 1.7.3?  "Target Milestone" isn't yet identified for this issue.
Comment 3 Andrew Clement CLA 2013-04-25 17:01:49 EDT
class literals are now supported, just committed that.

Arrays are not, that is more complicated because the parser doesn't appear to be allowing { } chars through as pseudotokens for the pointcut parser.

I'm not happy about abusing = to also mean 'contains' in addition to equality, but I haven't put any brainpower into a better syntax yet.
Comment 4 Matthew Adams CLA 2013-04-25 22:14:20 EDT
(In reply to comment #3)
> class literals are now supported, just committed that.
> 
Dude.  Sweet.

> Arrays are not, that is more complicated because the parser doesn't appear
> to be allowing { } chars through as pseudotokens for the pointcut parser.
> 
Not sure what that means to me, a mere layman.

> I'm not happy about abusing = to also mean 'contains' in addition to
> equality, but I haven't put any brainpower into a better syntax yet.
I'm ok with it since given

public @interface Foo { String[] value(); }

the following Java sources are equivalent:

@Foo("goo")

@Foo({"goo"})

The only problem I can forsee is when you match on syntax (not type) and want to match an annotation that has a single valued attribute.  For example, if "=" is overloaded to embody both "equals" & "contains" and given

package org.example.foo;
public @interface Foo { String value; }

and

package org.example.bar;
public @interface Bar { String[] value; }

then you could not create a type expression that will select, say, any class annotated with any annotation that has a single-valued String attribute with value "goo":

(@*(value = "goo") *) // ambiguous if "=" means "equals" or "contains"

The above would not be ambiguous if "=" were not overloaded.  Given that overloading would make that kind of unique selection impossible, I suppose that I'm left supporting the idea of ensuring "=" is not overloaded, and being forced to use either "=" or "{...}" to differentiate.
Comment 5 Matthew Adams CLA 2013-04-25 22:25:21 EDT
(In reply to comment #4)
> > I'm not happy about abusing = to also mean 'contains' in addition to
> > equality, but I haven't put any brainpower into a better syntax yet.
> I'm ok with it since given
> 
...
> The above would not be ambiguous if "=" were not overloaded.  Given that
> overloading would make that kind of unique selection impossible, I suppose
> that I'm left supporting the idea of ensuring "=" is not overloaded, and
> being forced to use either "=" or "{...}" to differentiate.

Just want to be clear that I flip-flopped on my preference after typing out loud and think that "=" should NOT be overloaded with both "equals" and "contains".  "=" should only match single-valued annotation attributes and "{...}" should only match multivalued annotation attributes.

:)