XText 中的简单导入指令
Simple import instruction in XText
我想将 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])?;
假设我只想扩展在给定 class 之前定义的 classes,并且只扩展那些以与 [=57= 相同的第一个字母开头的那些] 正在定义中。
推荐的方法是通过 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)
}
}
}
我希望能够像这样从导入的文件中访问 class 声明:
// --- 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 中发布了代码。
嗨,我真的跟不上你。您要么简单地使用 import Uri,尽管不鼓励 https://www.eclipse.org/forums/index.php?t=msg&th=1078818&goto=1736351&#msg_1736351,要么您通过调整名称提供程序(将元素命名为 . elementname) 和 importednamespaceawarelocalscopeprovider(将 Import xxx 转为 Import xxx.*)
能否就您的要求提供更多提示
您提到的所有服务都有不错的默认实现,因此您不需要实现它们,除非您想更改它们的工作方式。
确实不鼓励使用 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.),它们将自动结束在范围提供程序中。
我想将 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])?;
假设我只想扩展在给定 class 之前定义的 classes,并且只扩展那些以与 [=57= 相同的第一个字母开头的那些] 正在定义中。
推荐的方法是通过 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)
}
}
}
我希望能够像这样从导入的文件中访问 class 声明:
// --- 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 中发布了代码。
嗨,我真的跟不上你。您要么简单地使用 import Uri,尽管不鼓励 https://www.eclipse.org/forums/index.php?t=msg&th=1078818&goto=1736351&#msg_1736351,要么您通过调整名称提供程序(将元素命名为 . elementname) 和 importednamespaceawarelocalscopeprovider(将 Import xxx 转为 Import xxx.*)
能否就您的要求提供更多提示
您提到的所有服务都有不错的默认实现,因此您不需要实现它们,除非您想更改它们的工作方式。
确实不鼓励使用 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.),它们将自动结束在范围提供程序中。