Bug 223225 - [DOM] IMemberValuePairBinding does not desugar single values into one-element arrays
Summary: [DOM] IMemberValuePairBinding does not desugar single values into one-element...
Status: VERIFIED FIXED
Alias: None
Product: JDT
Classification: Eclipse Project
Component: Core (show other bugs)
Version: 3.3.1   Edit
Hardware: PC Windows XP
: P3 normal (vote)
Target Milestone: 3.7 M1   Edit
Assignee: Olivier Thomann CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2008-03-19 13:34 EDT by Kevin CLA
Modified: 2010-08-03 09:31 EDT (History)
4 users (show)

See Also:


Attachments
Proposed fix + regression test (5.67 KB, patch)
2010-07-21 12:34 EDT, Olivier Thomann CLA
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Kevin CLA 2008-03-19 13:34:52 EDT
Build ID: Build id: M20071023-1652

Steps To Reproduce:
1. Define an annotation type A with a attribute v of array type, e.g., @interface A { String[] v(); }
2. Create an annotation of type A that provides a single value for v, e.g., @A(v = "hello") 
3. Parse the AST for the compilation unit containing the annotation created in step 2, requesting type bindings
4. When querying the IAnnotationBinding for the annotation created in step 2, the value for attribute v will be a single object (in the example, a string), while the type binding for v declares v to be of array type.  Arguably, IAnnotationBinding should desugar the value for v into an array to conform with the declared attribute type and return an Object[] for its value.  This would achieve consistency with what is returned if a single-element array is declared in the annotation, e.g., with @A(v = {"hello"}).

More information:
The following is a test file that exhibits the problem.  The IAnnotationBindings for the annotations on marker(), single(), and singleValue() return a String object as the value of attribute "value", while the other methods return an Object[].  Arguably, and Object[] should always be returned.

public class SingleElementArrayAnnotationTest {
	
	private @interface Strings {
		String[] value() default "default element";
	}
	
	@Strings
	public void marker() {
		// nothing
	}
	
	@Strings("single element")
	public void single() {
		// nothing
	}
	
	@Strings(value = "single element")
	public void singleValue() {
		// nothing
	}
	
	@Strings({"single element"})
	public void singleArray() {
		// nothing
	}
	
	@Strings(value = {"single element"})
	public void singleArrayValue() {
		// nothing
	}
	
	@Strings({"one", "two", "three"})
	public void multi() {
		// nothing
	}

	@Strings(value = {"one", "two", "three"})
	public void multiValue() {
		// nothing
	}

}
Comment 1 Philipe Mulet CLA 2008-03-26 08:58:53 EDT
The binding reflects exactly what is in the source. If it wasn't wrappered, then no free wrappering occurs. For each MemberValuePair, you can find the corresponding method binding, which carries the expected array type.

The same is true for arguments to varargs methods which are not wrappered either in an array type.
Comment 2 Kevin CLA 2008-03-28 19:02:48 EDT
Philippe, I guess I would expect annotation bindings to be a canonical form of whatever appears in the source.  Thus, a MemberValuePair AST node can represent the source as-is, but I thought a binding would turn what's in the source into a single, canonical representation.  

I understand your explanation, though, and I think in this case the documentation of IMemberValuePairBinding should explain this, and it would be nice to have a way of getting to the (fully) desugared annotation value.

- IMemberValuePairBinding's Javadoc states that it represents the "resolved instance of an annotation's member value pair".  Likewise, getValue() is supposed to return the "resolved [annotation] value".  I interpreted "resolved" as "after desugaring" or "canonical".  And some desugaring does happen: an omitted "value =" is added, and default values are added as well (when requesting "all" member value pairs from an IAnnotationBinding), just not arrays around single values.  It would be nice if the documentation for IMemberValuePairBinding clarified how much resolution clients can expect from getValue().

- Can there be a method similar to getValue() that returns such a canonical value, i.e., with arrays around it where needed?  It just seems unsatisfying that clients have to worry about what's written in the source when querying annotation bindings.  If something like getCanonicalValue() existed then clients wouldn't have to do that.  I think that would really help using this interface.
Comment 3 Philipe Mulet CLA 2008-03-29 05:11:40 EDT
Anything is possible, but adding a new API post 3.4M6 would be exceptional, and nothing we would motivate by adding a helper method like in this case.

So this would have to wait until 3.5.
Comment 4 Olivier Thomann CLA 2010-07-19 13:33:59 EDT
Markus, would you support such an API if added ?
I am thinking about the AST Parser tool.
Comment 5 Markus Keller CLA 2010-07-20 10:41:01 EDT
I think you should just fix the bug, i.e. make the existing API IMemberValuePairBinding#getValue() return an Object[] if the member is of an array type.

The analogy to vararg method invocations doesn't hold, because in that case, there is only a binding for the method declaration, but none for the method invocation (and the vararg sugar is at the invocation site). The IMemberValuePairBinding refers to a single member value pair, so it makes sense to canonicalize it there. Note that we already do process the values (we evaluate constant expressions like "a" + "bcd").

JDT UI currently only uses IMemberValuePairBinding to render Javadoc, and we won't be affected by this change. I actually didn't check this case when I wrote that code, but I assumed that the values would be canonicalized for free.
Comment 6 Olivier Thomann CLA 2010-07-21 12:34:15 EDT
Created attachment 174881 [details]
Proposed fix + regression test
Comment 7 Olivier Thomann CLA 2010-07-22 09:28:22 EDT
Released for 3.7M1.
Added regression test in org.eclipse.jdt.core.tests.dom.ASTConverter15Test#test344
Comment 8 Satyam Kandula CLA 2010-08-03 09:31:53 EDT
Verified for 3.7M1 using build I20100802-1800