Community
Participate
Working Groups
Example public void bar(String... args){ } The type returned form the SingleVariableDeclaration respresenting String... args shouldn't be a simple type. It should either be a array type or a sepecial vararg type. The problem is that is I ask the type for its binding I get a binding representing String. But from a type system point of view this is String[].
If the ellipsis (...) is not part of the position of the type, then there is no reason to get an array type. The corresponding single variable declaration is set as var args. Then you know this is a array type. However I agree that the type binding corresponding to the type should be an array binding.
In fact, it could be either way. When you get a type binding that is not a array binding, it can match the corresponding binding of the parameter in a method invocation. If you really want the array type binding, then get the corresponding argument of the method binding corresponding to the method declaration. Jim, any comment? We might want to clarify the specs to know what type binding is returned.
After thinking about it again I am not sure anymore if the type should be an array type. It should either be a special type (e.g. subclass of Type node) or a simple type as it is right now. The special type could offer two resolve methods to get both the binding for the simple and for the array type. If you access the type via IVariableBinding return from the declaration you already get an array type.
I propose that we keep existing behavior and simply clarify the spec to say that the binding for the type Foo in void fun(Foo... args) will be the type as written (i.e. Foo), and that if you'd rather have the array type (Foo[]), ask the method binding for the type binding of the last parameter.
Fine with me.
Added the following clarifying notes. Olivier, please add a test to cover this case. IMethodBinding.getParameterTypes() * Note that the binding for the last parameter type of a vararg method * declaration like <code>void fun(Foo... args)</code> is always for * an array type (i.e., <code>Foo[]</code>) reflecting the the way varargs * get compiled. However, the type binding obtained directly from * the <code>SingleVariableDeclaration</code> for the vararg parameter * is always for the type as written; i.e., the type binding for * <code>Foo</code>. SingleVariableDeclaration.isVarargs * Note that the binding for the type <code>Foo</code>in the vararg method * declaration <code>void fun(Foo... args)</code> is always for the type as * written; i.e., the type binding for <code>Foo</code>. However, if you * navigate from the method declaration to its method binding to the * type binding for its last parameter, the type binding for the vararg * parameter is always an array type (i.e., <code>Foo[]</code>) reflecting * the way vararg methods get compiled.
I will add test case to check we have the right behavior.
Regression tests added in ASTConverter15Test.test0131 and test0132.
Also test0143.
Reopening since these seems to have changed again: I have the following test case: public static final String format(String key,Object... args){ return MessageFormat.format(key,args); } Asking the SingleVariableDeclaration representing Object... args in format if it is a vararg I get true. If I ask the declaration for its binding and than its type I get an array type back. fDeclaration.resolveBinding().getType().isArray() (boolean) true What are we going to do with this. We can't change this again since clients might rely on the current behaviour.
Philippe, cc you since Olivier is on vacation.
If you ask the declaration for its type and then its binding, you should get Object and not Object[]. I cannot check myself, because Eclipse doesn't run on the machine I am using.
We should be REALLY REALLY careful changing this again. This might break existing clients relying on the current implementation.
If you do this: fDeclaration.getType().resolveBinding().isArray() do you get true? I don't this so. I don't see what is wrong with your comment 10. It follows the specifications. So I don't see what we could change. From my point of view, there is absolutely nothing to change.
Yes, in the given example import java.text.MessageFormat; public class Z { public static final String format(String key, Object... argssss){ return MessageFormat.format(key,argssss); } void use() { format("key", "value"); } } when I ask the following question to fDeclaration which represent the method declaration of format I get the following: fDeclaration.isVarargs() (boolean) true fDeclaration.toString() (java.lang.String) public static final String format(String key,Object... argssss){ return MessageFormat.format(key,argssss); } ((SingleVariableDeclaration)fDeclaration.parameters().get(1)).isVarargs() (boolean) true ((SingleVariableDeclaration)fDeclaration.parameters().get(1)).resolveBinding().getType().isArray() (boolean) true ((SingleVariableDeclaration)fDeclaration.parameters().get(1)).toString() (java.lang.String) Object... argssss I there something I am missing here ?
You are getting confused between the type of the binding of the single variable declaration that is an array and the binding of the type of the single variable declaration that is not an array. This is in line with the specs and I don't see anything to change in this area. ((SingleVariableDeclaration)fDeclaration.parameters().get(1)).getType().resolveBinding().isArray() answers false as expected. because the type's positions don't include the '...'. Ok to close?
Closing as FIXED since the described problem in comment 10 is not a problem, but the original problem is indeed fixed.
OK I see. But this is a tricky detail ;-). May be we should add this to the Java doc.
Jim, I let you be the judge to find out if we need anything else in the doc. For me the isVarArgs() on SingleVariableDeclaration doc is pretty clear.