我正在尝试在我的DSL中使用交叉引用。这是语法的精简版本(标准示例DSL的修改版本):
grammar org.xtext.example.mydsl.MyDsl with org.eclipse.xtext.common.Terminals
generate myDsl "http://www.xtext.org/example/mydsl/MyDsl"
Releases:
releases+=Release*
;
terminal VERSION : ('0'..'9')+'.'('0'..'9')+('.'('0'..'9'|'x')+)?;
Release:
'release' version = VERSION ('extends' parent = [Release|VERSION])?
;
由于我没有使用标准的name = ID
模式,因此我按照this blog post关于如何创建自己的IQualifiedNameProvider
:
public class MyDslQNP extends DefaultDeclarativeQualifiedNameProvider {
QualifiedName qualifiedName(Release e) {
Package p = (Package) e.eContainer();
return QualifiedName.create(p.getName(), e.getVersion());
}
}
关于SO的另一个答案,我收集到了我应该实现自己的范围提供者:
public class MyDslScopeProvider extends AbstractDeclarativeScopeProvider {
IScope scope_Release_parent(Release release, EReference ref) {
Releases releases = (Releases) release.eContainer();
return Scopes.scopeFor(releases.getReleases());
}
}
我还在运行时模块中绑定了这些:
public class MyDslRuntimeModule extends
org.xtext.example.mydsl.AbstractMyDslRuntimeModule {
@Override
public Class<? extends IQualifiedNameProvider> bindIQualifiedNameProvider() {
return MyDslQNP.class;
}
@Override
public Class<? extends IScopeProvider> bindIScopeProvider() {
return MyDslScopeProvider.class;
}
}
运行生成的编辑器时,我创建了一个如下所示的文件:
release 1.2.3
release 1.2.2 extends 1.2.3
问题是(1)编辑器不会在'extends'子句上自动完成,(2)编辑器显示错误消息Couldn't resolve reference to Release '1.2.3'
。
我错过了什么?
答案 0 :(得分:2)
您的QualifiedNameProvider似乎创建了虚假的限定名称,例如版本1.2.2的名称将有两个段[release] [1.2.2],其中查找将搜索[release] [1] [2] [2]。
请尝试创建一个合适的合格名称:
QualifiedName qualifiedName(Release e) {
Package p = (Package) e.eContainer();
QualifiedName release = getConverter().toQualifiedName(e.getVersion());
return QualifiedName.create(pack.getName()).append(releaseSuffix);
}
答案 1 :(得分:1)
Scopes.scopeFor是一个静态方法,因此不使用已配置的IQualifiedNameProvider。 您需要明确使用它 Scopes.scopeFor(Iterable,Function,IScope)
但是在您的情况下,您根本不需要在作用域提供程序中进行特殊处理,因为具有合格名称提供程序的本地元素将自动放在作用域上。