Community
Participate
Working Groups
2005018 Also field bindings can be either 'generic' or 'parametrized'. A generic type returns generic field bindings, a parametrized type the 'parametrized field' bidings. Field type can be different on the two. class A<T> { public T t; // generic variable binding. var type: T { new A<String>.t= null; // parametrized variable binding. var type: String } } Depending on the result from bug 80800 we should have methods IVariableBinding.isGenericField IVariableBinding.isParametrizedField IVariableBinding.isRawField IVariableBinding.getGenericField
Parameterized field declarations and raw fields references make sense. But unlike types and methods, there are no generic field declarations (i.e., ones that introduce new type variables). In the example, the binding for the generic type A owns bindings for a (normal) field t whose field type is the type variable binding T; the binding for the parameterized type A<String> owns bindings for a parameterized field t whose field type is the type variable binding T. In the spirit of bug 80800, IVariableBinding needs - isParameterizedField() - getTypeArguments() - isRawField() - getFieldDeclaration()
What is getTypeArguments() doing?
I spoke too soon. getTypeArguments() is not needed, because the parameterized field declaration has its type variables substituted. In the example, I should have said "the binding for the parameterized type A<String> owns bindings for a parameterized field t whose field type is the (substituted) type String." Looking at the compiler side, I'm not sure there is such a thing as a raw field reference. Olivier, maybe you could advise on whether there is such a thing.
IMO the three queries - isParameterizedField() - getTypeArguments() - isRawField() don't make sense on fields. A field is a member of a type, and you can always ask IVariableBinding#getDeclaringClass() to get its declaring type. The declaring type in turn can be generic, raw, or parameterized. Compare this to a non-generic method with a type variable as parameter type: new ArrayList<String>().add(""); The method binding for add("") is not a generic, nor a parameterized, nor a raw method. It's just a plain method whose parameter's type is String. Its #getMethodDeclaration() returns another non-generic method whose parameter's type is the type variable E. To summarize: I support the request for IVariableBinding#getFieldDeclaration(), which returns the field declaration in the generic version of the declaring type. The other methods are IMO not appropriate. We have to decide what the method will return for a local variable binding. If it returns null, then #getFieldDeclaration() is a good name. If it returns the same binding, then the method should better be called #getVariableDeclaration(). I tend to prefer #getVariableDeclaration().
I would have thought that all members of a generic type would also call themself 'generic', and all members of raw or parametrized call themselve raw or parametrized. Signatures or implementions are different for these members and I think calling them parametrized makes sense, it doesn't require having own parameters.
For me the questions isGeneric/isParameterized are basically short cuts for asking if getTypeParameters() != null / getTypeArguments != null. Since Fields can't declare own type parameters adding these methods to fields doesn't seem to be the right thing. However, what we need for each member is a way to navigate from the element in the instantiated type to the one in the generic type. This should be offered for variable bindings as well. Navigation wise there is an interesting question with methods having type parameters. Consider the following case: class <A> { <X> void foo(X x) { } } Here, both the type binding for A and the method binding for foo are generic. Now we create an instance of A, A<String> In this binding A is parameterized, but foo is still generic. Now call new A<String>().foo(new Number()); The method binding representing the call foo now is parameterized. So for method binding foo(Number) there is the question what getMethodDeclaration returns: A<String>#foo(X) or A<T>#foo(X). In any case we need methods to navigate to both "declaration" bindings. I would prefer that 'foo(Number)'.getMethodDeclaration() returns A<T>#foo(X) and that we have another method that navigates from foo(Number) to A<String>#foo(X).
agreed, I take back the requests for IVariableBinding.isGenericField IVariableBinding.isParametrizedField IVariableBinding.isRawField That leaves IVariableBinding.getVariableDeclaration - for params and locals always returning itself - for fields in a parametrized type it return the corresponding field in the generic type or itslef if not in a parametrized type
Jeem, the requested functionality is important for JDT/UI. Otherwise we can't find references to fields by comparing bindings since for fields inside parameterized types the binding for the declaration is not equals to the binding referencing such a field.
Dirk, How does this sound? /** * Returns the binding for the variable declaration corresponding to this * variable binding. For a binding for a field declaration in an instance * of a generic type, this method returns the binding for the corresponding * field declaration in the generic type. For other variable bindings, * including all ones for local variables and parameters, this method * returns the same binding. * * @return the variable binding for the originating declaration * @since 3.1 */ public IVariableBinding getVariableDeclaration();
+1
Released API addition (and stub implementation). Olivier, Over to you for implementation.
Fixed and released in HEAD. Regression tests added in ASTConverter15Test.test0141 and test0142.
Verified in 20050330-0500