Resolving type parameters in the Jvm types [message #1152927] |
Thu, 24 October 2013 04:55  |
Eclipse User |
|
|
|
Hi,
I'm using Xbase and JvmType and the Java model inferer support in a DSL
that is supposed to make it easier to implement event handlers, e.g. for
swing and javafx. In the generated Java there will be implementations of
various listeners, based on the types and methods that are found when
traversing/analyzing the API. E.g. a javafx TextField has a
textProperty() method and its return value is a StringProperty which has
an addListener(ChangeListener) method, so I need an implementation of
ChangeListener to react to changes to a text field. The generated code
in this case looks like the following:
public class textField1TextListener implements ChangeListener<?> {
public void changed(final ObservableValue<? extends ?> arg0, final
? arg1, final ? arg2) {
The type parameters complicates the matter, since the type signatures of
the relevant classes are something like this (a bit simplified):
class ObservableValue<T> {
addListener(ChangeListener<T>)
}
class StringProperty extends ObservableValue<String> {
}
The problem with my generated code is that the types refer to type
parameters that are not resolved against the StringProperty context and
its <String> type argument to ObservableValue.
This is a common problem when working with Java types and I'm sure Xtext
has code for this already. Are there any utility classes that I can
(re)use for solving my problem?
Hallvard
|
|
|
Re: Resolving type parameters in the Jvm types [message #1159179 is a reply to message #1152927] |
Mon, 28 October 2013 06:50  |
Eclipse User |
|
|
|
Hi,
Considering a JvmTypeReference R1 in a JvmType T1 with type parameters (for example ChangeListener<T> fron the addListener method declared in ObservableValue<T>) and considering a JvmTypeReference R2 of the JvmType (for example ObservableValue<String>), if I want to get R1 with type parameters substituted (thus to get ChangeListener<String>), I do that:
val mapping = new ConstraintAwareTypeArgumentCollector(containerTypeRef.owner).getTypeParameterMapping(containerTypeRef)
new StandardTypeParameterSubstitutor(mapping, containerTypeRef.owner).substitute(tr)
containerTypeRef is a LightweightTypeReference created from R2 (check XBaseValidator to see how to create such a LightweightTypeReference, there is a helper method there).
tr is a LightweightTypeReference created from R1.
Problem with that is that it does not take the hierarchy of classes into account (if for example R1 is actually defined in a super class of T1 but you only have R2 a reference to T1).
Here is my raw code for it, it contains things that are specific to my grammar, to check who owns the reference (and thus the type parameters that must be substituted:
private def LightweightTypeReference resolveType(LightweightTypeReference portTypeRef, LightweightTypeReference containerTypeRef, Port port) {
val ac = containerTypeRef.type.associatedAbstractComponent
val tr = if (!(ac.provides.contains(port) || ac.requires.contains(port)) && ac.specializes != null) {
val nptr = ac.specializes.toLightweightTypeReference(port.eResource)
resolveType(portTypeRef, nptr, port)
} else {
portTypeRef
}
val mapping = new ConstraintAwareTypeArgumentCollector(containerTypeRef.owner).getTypeParameterMapping(containerTypeRef)
new StandardTypeParameterSubstitutor(mapping, containerTypeRef.owner).substitute(tr)
}
|
|
|
Powered by
FUDForum. Page generated in 0.26798 seconds