scope - XText 中的简单导入指令

标签 scope xtext xtend

我想将 XText 中另一个文件中的一些对象添加到范围中。为了说明我需要什么,我有这个玩具语法:

grammar org.xtext.example.mydsl.MyDsl with org.eclipse.xtext.common.Terminals
generate myDsl "http://www.xtext.org/example/mydsl/MyDsl"

Model:
   (imports += Import)*
   (classes += ClassDef )*;

Import:
    'import' filename += STRING;    

ClassDef:
    'class' name=ID ('extends' extends=[ClassDef])?;

假设我希望能够仅扩展在给定类之前定义的类,并且仅扩展那些以与所定义的类相同的首字母开头的类。

推荐的方法是通过 scoping 。这是在单个文件中执行此操作的范围提供程序:

package org.xtext.example.mydsl.scoping
import ....

class MyDslScopeProvider extends AbstractMyDslScopeProvider {
    override getScope(EObject context, EReference reference){
        if(reference ==  MyDslPackage.Literals.CLASS_DEF__EXTENDS){
            if(! (context instanceof ClassDef) ) {return IScope.NULLSCOPE }
            val root = (context as ClassDef).getRootContainer
            val classes = root.getAllContentsOfType(ClassDef)
            val before = classes.subList(0, classes.indexOf(context))
            val fstLetter = (context as ClassDef).name.charAt(0)
            val haveSame1stLetter = before.filter[name.charAt(0) == fstLetter]          
            return Scopes::scopeFor(haveSame1stLetter)
        }
    }
}

我希望能够从导入的文件中访问类声明,如下所示:

// --- c ---
class Xlib
class Xextend extends Xlib

// --- main.mydsl ---
import "lib.mydsl"
class A
class Xmain extends Xlib

我发现了一些关于使用 importURI 的相互矛盾的建议,但它似乎对我不起作用,而且现在似乎已经过时了。

文档提到,对于跨资源引用,我可能需要:

  • 创建 IGlobalScopeProvider 的实例,
  • 将元素导出为 IResourceDescription 的一部分
  • QualifiedName 及其字符串表示形式之间进行转换
  • 实现并绑定(bind)我自己的IDefaultResourceDescriptionStrategy
  • IContainer.Manager 获取 IContainer
  • IContainer 获取 IResourceDescriptions(注意复数形式)

...还有更多其他事情。不幸的是,它们并没有整合成一个连贯的画面,说明我必须做什么才能实现期望的行为。


编辑:按照斯文的建议,我想出了解决方案。如果有人感兴趣——我已将代码发布在 this gist 中。

最佳答案

您提到的所有服务都有不错的默认实现,因此您不需要实现它们,除非您想更改它们的工作方式。

确实不鼓励使用 importUri 机制,但您应该使用基于名称的链接,这更可靠。

Xtext 自动为您维护一个包含全局可见限定名称的索引。索引有两侧:

<强>1。对指数的贡献

在索引期间,ResourceDescriptionManager 被要求提供命名元素。默认实现将提供具有属性名称的任何元素。如果您想更改该行为,可以子类化 DefaultResourceDescriptionStrategy 并覆盖 createEObjectDescriptions。例如,您可以使用资源的简单名称导出模型的根元素,以允许

Import :
   'import' referencedModel+=[Model|STRING]
;

这仅允许导入文件,如果您想支持从不同文件夹导入文件,我建议使用命名空间。

namespace foo;
type Bar {}

其他文件

import foo.Bar
type Foo extends Bar

<强>2。使用索引

范围提供程序自动委托(delegate)给 GlobalScopeProvider,后者将提供索引中的描述。因此,如果您确保元素索引正确(请参阅 1),它们将自动出现在范围提供程序中。

关于scope - XText 中的简单导入指令,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40785253/

相关文章:

python - 在嵌套变量范围内声明的变量名称是什么?

java引用不在范围内的对象

java - 我可以将 XText 用于涉及 XML 文件类型的 DSL 吗?

xtext - xbase 中带有二元运算符的 java 表达式不起作用

java - 我需要使用 Xtend/Acceleo 吗?

ajax - 从 $.each 匿名函数获取变量值

ruby-on-rails-3 - 将 Rails 3 范围合并到类方法中

java - 从另一个 Eclipse View 监听 XText 编辑器中的 EObject 更改

java - 如何使用 xtend 设置 java 注释的多个属性(使用 xbase)

java - 如何测量每个输入文件的 Xtend 翻译时间