【问题标题】:Simple import instruction in XTextXText 中的简单导入指令
【发布时间】:2016-11-25 05:40:52
【问题描述】:

我想将 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 与其字符串表示之间进行转换
  • 实现并绑定我自己的IDefaultResourceDescriptionStrategy
  • IContainer.Manager 获取IContainer
  • IContainer得到IResourceDescriptions(注意复数形式)

...以及更多其他内容。不幸的是,它们并没有形成一个连贯的画面,说明我必须做什么才能实现预期的行为。


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

【问题讨论】:

    标签: scope xtext xtend


    【解决方案1】:

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

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

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

    1.对索引的贡献

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

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

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

    namespace foo;
    type Bar {}
    

    其他文件

    import foo.Bar
    type Foo extends Bar
    

    2。使用索引

    范围提供程序自动委托给 GlobalScopeProvider,它将提供索引中的描述。因此,如果您确保元素被正确索引(参见 1.),它们将自动在范围提供程序中结束。

    【讨论】:

      【解决方案2】:

      您好,我不能真正关注您。要么你简单地使用 import Uri 尽管它不鼓励https://www.eclipse.org/forums/index.php?t=msg&th=1078818&goto=1736351&#msg_1736351 要么你使用基于命名空间的作用域(不知道你是否想要支持相对导入或花哨的 Uri 方案)通过调整名称提供程序(给元素名称.elementname)和importednamespaceawarelocalscopeprovider(将Import xxx转为Import xxx.*)

      能否请您提供更多关于您的要求的提示

      【讨论】:

      • 嗨,我试着举一个例子来说明我想要实现的目标
      • 您是否有多个文件夹/包/项目和相对/绝对导入或只有当前文件夹旁边的文件
      • 当前所有文件都在同一个文件夹中。但我希望将来可以使用文件夹。
      • 然后使用 import Uri
      猜你喜欢
      • 2013-10-26
      • 1970-01-01
      • 1970-01-01
      • 2015-08-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-07-30
      相关资源
      最近更新 更多