XText交叉引用:如何使用其上下文作为限定符在本地唯一ID之间建立引用?

时间:2013-07-11 14:31:58

标签: xtext

我遇到了交叉引用终端的问题,这些终端只是本地唯一的(在它们的块/范围内),但不是全局的。我发现tutorials描述了我如何使用完全限定名称或包声明,但我的情况在语法上与示例略有不同,我无法更改DSL以支持显式完全限定名称或包声明之类的内容

在我的DSL中,我有两种类型的结构化JSON资源:

  • 包含我的数据的实例。
  • 元模型,包含我的数据的类型信息等。

我可以轻松地解析这两个,并使用以下Java代码段获取EMF模型:

new MyDSLStandaloneSetup().createInjectorAndDoEMFRegistration();
ResourceSet rs = new ResourceSetImpl();
rs.getResource(URI.createPlatformResourceURI("/Foo/meta.json", true), true);
Resource instanceResource= rs.getResource(URI.createPlatformResourceURI("/Bar/instance.json", true), true);
EObject eobject = instanceResource.getContents().get(0);

简单的例子:

meta.json

{
    "toplevel_1": {
        "sublevels": {
            "sublevel_1": {
                "type": "int"
            },
            "sublevel_2": {
                "type": "long"
            }
        }
    },
    "toplevel_2": {
        "sublevels": {
            "sublevel_1": {
                "type": "float"
            },
            "sublevel_2": {
                "type": "double"
            }
        }
    }
}

instance.json

{
    "toplevel_1": {
        "sublevel_1": "1",
        "sublevel_2": "2"
    },
    "toplevel_2": {
        "sublevel_1": "3",
        "sublevel_2": "4"
    }
}

由此我想推断:

  • toplevel_1:sublevel_1的类型为int,值为1
  • toplevel_1:sublevel_2的类型为long,值为2
  • toplevel_2:sublevel_1的类型为float,值为3
  • toplevel_2:sublevel_2的类型为double,值为4

我能够交叉引用独特的toplevel-elements并迭代所有的子级别,直到我找到了我正在寻找的那些,但是对于我的用例来说效率非常低且复杂。另外,我没有让生成的编辑器以这种方式在子级别之间建立链接。

我玩链接和范围,但我不确定我真正需要什么,如果我必须扩展providers-classes AbstractDeclarativeScopeProvider和/或DefaultDeclarativeQualifiedNameProvider。

最好的方法是什么?

另见:

1 个答案:

答案 0 :(得分:2)

经过一些试验和错误后,我用ScopeProvider解决了我的问题。 主要问题是我并不真正理解Xtext术语中的作用域是什么,以及我必须提供什么。

查看documentation的签名:

IScope scope_<RefDeclaringEClass>_<Reference>(<ContextType> ctx, EReference ref)

在我的示例语言中:

  • RefDeclaringEClass 将引用来自instance.json的Sublevel,
  • 参考到meta.json对Sublevel的交叉引用,
  • ContextType 将匹配 RefDeclaringEClass

使用ctx的eContainer,我可以从instance.json获取Toplevel。 这个Toplevel已经有一个来自meta.json的匹配Toplevel的交叉引用,我可以用它来从meta.json获取Sublevels。这个Sublevels集合基本上是当前Sublevel应该是唯一的范围。

为了获得IScope,我使用了Scopes#scopeFor(Iterable)。

我没有在这里发布任何代码,因为实际的语法更大/不同,因此并没有真正帮助解释。