3

I'm trying to get cross-references to work in my DSL. Here's a stripped down version of the grammar (a modified version of the standard example 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])?
    ;

Since I'm not using the standard name = ID pattern, I followed this blog post about how to create my own IQualifiedNameProvider:

public class MyDslQNP extends DefaultDeclarativeQualifiedNameProvider {
    QualifiedName qualifiedName(Release e) {
        Package p = (Package) e.eContainer();
        return QualifiedName.create(p.getName(), e.getVersion());
    }
}

From another answer on SO, I gathered that I should implement my own scope provider:

public class MyDslScopeProvider extends AbstractDeclarativeScopeProvider {
    IScope scope_Release_parent(Release release, EReference ref) {
        Releases releases = (Releases) release.eContainer();
        return Scopes.scopeFor(releases.getReleases());
    }
}

I've also bound these in the runtime module:

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;
    }

}

When running the generated editor I create a file which looks like this:

release 1.2.3
release 1.2.2 extends 1.2.3

The problem is that (1) the editor won't autocomplete on the 'extends' clause, and (2) the editor shows an error message Couldn't resolve reference to Release '1.2.3'.

What am I missing?

JesperE
  • 63,317
  • 21
  • 138
  • 197

2 Answers2

2

Your QualifiedNameProvider seems to create bogus qualified names, e.g. the name for the release 1.2.2 would have two segments [release][1.2.2] where the lookup will search for [release][1][2][2].

Please try to create a proper qualified name like this:

QualifiedName qualifiedName(Release e) {
    Package p = (Package) e.eContainer();
    QualifiedName release = getConverter().toQualifiedName(e.getVersion());
    return QualifiedName.create(pack.getName()).append(releaseSuffix);        
}
Sebastian Zarnekow
  • 6,609
  • 20
  • 23
1

Scopes.scopeFor is a static method and therefore doesn't use the configured IQualifiedNameProvider. You need to pass it in explicitly using Scopes.scopeFor(Iterable, Function, IScope)

But in your case you don't need the special handling in the scope provider at all, since local elements with a qualified name provider are being put on the scope automatically.

Sven Efftinge
  • 3,065
  • 17
  • 17
  • Ok, so removing the scope provider makes the autocompletion work, but it still fails to resolve the reference. – JesperE Apr 26 '12 at 07:52