使用自定义终端规则的Xtext交叉引用

时间:2012-04-25 12:54:41

标签: xtext

我正在尝试在我的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'

我错过了什么?

2 个答案:

答案 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)

但是在您的情况下,您根本不需要在作用域提供程序中进行特殊处理,因为具有合格名称提供程序的本地元素将自动放在作用域上。