【发布时间】: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 中发布了代码。
【问题讨论】: