XText中的简单导入指令

时间:2016-11-24 11:28:12

标签: 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及其字符串表示
  • 之间进行转换
  • 实现并绑定我自己的IDefaultResourceDescriptionStrategy
  • IContainer
  • 获取IContainer.Manager
  • IResourceDescriptions
  • 获取IContainer(请注明复数形式)

......以及更多其他事情。不幸的是,它们并没有加起来描述我为实现理想行为所必须做的事情。

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

2 个答案:

答案 0 :(得分: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.),它们将自动结束于范围提供程序中。

答案 1 :(得分:0)

嗨,我真的不能跟着你。你可以简单地使用import Uri虽然不鼓励https://www.eclipse.org/forums/index.php?t=msg&th=1078818&goto=1736351&#msg_1736351或你使用基于命名空间的范围(不知道你是否想要支持相对导入或花哨的Uri方案)通过调整名称提供者(给元素name .elementname)和importednamespaceawarelocalscopeprovider(将导入xxx转换为导入xxx。*)

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