2

在 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?我希望不是。

谢谢你的任何提示。

4

1 回答 1

0

解决了。getCollectionType()是正确的。不正确的是输入,我创建JvmTypeReference. 它们并非直接源自已解析的模型。只有顶级元素在我的 DSL 中明确指定了类型。所有子元素类型都是使用 Xtext“自省”以级联方式从上到下推断的。推断类型存储在模型本身中;各种其他的东西都依赖于它们,比如验证。要将推断的 JvmTypeReference 存储在 Model AST 中,必须对其进行复制。

我没有正确创建副本。错误的库调用。

错误的:

public JvmTypeReference createDefensiveCopyOfJvmTypeReference(JvmTypeReference typeReference) {
    return typeReferences.createTypeRef(typeReference.getType());
}

正确的:

public JvmTypeReference createDefensiveCopyOfJvmTypeReference(JvmTypeReference   typeReference) {
    return EcoreUtil.copy(typeReference);
}

好吧,这TypeReferences#createTypeRef()并不完全错误。它创建所需类型的副本,但表现出类似于 Java 中的“类型擦除”。

我也在Xtext 论坛上提出了这个问题。

查看我的DeepCloneDSL项目以获取完整的源代码。

PS
为什么我们要制作副本JvmTypeReference?以及来自 Xtext 常见类型的其他实例?JvmTypeReference是一个复杂的类型,EObject它本身就是 AST 的一个片段,一个模型的片段。通过设置类型JvmType或类似的属性,将模型片段插入另一个模型;它不能被插入两次或同时在两个不同的模型中。Xtext 本身会阻止某些操作,有些操作更棘手,必须找到困难的方法

于 2012-12-18T14:13:42.510 回答