在Xtext中,我试图编写一个实用程序方法来返回集合类型(泛型类型),其中集合类型由解析器创建的JvmTypeReference表示,我需要知道类型参数:
@Inject TypeReferences typeReferences;
public JvmType getCollectionType(JvmTypeReference clazz) {
if (typeReferences.isInstanceOf(clazz, Collection.class)) {
collectionType = typeReferences.getArgument(clazz, 0);
return collectionType;
}
}
示例1:对于输入java.util.List<String>
我希望该方法返回java.lang.String
,
示例2:输入java.util.Set<a.b.m.Book>
以返回a.b.m.Book
。
我需要我的生成器的集合类型参数类型。
声音良好的typeReferences.getArgument(..)
会返回JvmParameterizedTypeReference: E
,其中getType()
会JvmTypeParameter <E> java.util.List
。嗯。我进入了死胡同。
是否可能或类型擦除是否也适用于JvmTypeReference
?我希望不会。
感谢您的任何提示。
答案 0 :(得分:0)
解决。 getCollectionType()
是正确的。不正确的是输入,我创建JvmTypeReference
的方式。它们并非直接来自解析的模型。只有顶级元素在我的DSL中明确指定了类型。所有子元素类型都是使用Xtext“introspection”以级联方式从上到下推断出来的。推断类型存储在模型本身中;各种其他东西都依赖于它们,比如验证。要在模型AST中存储推断的JvmTypeReference,必须复制它。
我没有正确创建副本。错误的图书馆电话。
错:
public JvmTypeReference createDefensiveCopyOfJvmTypeReference(JvmTypeReference typeReference) {
return typeReferences.createTypeRef(typeReference.getType());
}
正确:
public JvmTypeReference createDefensiveCopyOfJvmTypeReference(JvmTypeReference typeReference) {
return EcoreUtil.copy(typeReference);
}
嗯,TypeReferences#createTypeRef()
并非完全错误。它创建了所需类型的副本,但展示了与Java类似的“类型擦除”。
我也在Xtext forum上提出了这个问题。
检查我的DeepCloneDSL项目是否有完整的源代码。
P.S。
为什么我们要复制JvmTypeReference
?和Xtext常见类型的其他实例? JvmTypeReference
是一个复杂类型EObject
,它本身就是AST的一个片段,是模型的一个片段。通过设置类型JvmType
或类似的属性,可以将模型片段插入到另一个模型中;它不能插入两次或同时在两个不同的型号中。 Xtext本身阻止了一些这样的行为,有些行为更棘手,必须找到the hard way。