Search code examples
javadslmodelingxtextxtend

Xtext 2.9 scope provider


Xtext 2.9 changed the way scope providers work and I don't understand how they work now.

Let's say I have the following grammar:

grammar org.xtext.example.mydsl.MyDsl with org.eclipse.xtext.common.Terminals

generate myDsl "http://www.xtext.org/example/mydsl/MyDsl"

Model:
    ((things+=Thing) | (refs+=Reference))*
;

Thing:
    'thing' name=ID '{'
        stuff += Stuff* 
    '}'
;

Stuff:
    'stuff' name=ID
;

Reference:
    'reference' thing=[Thing] stuff=[Stuff] 
;

For the Reference clause to work, I need a scope provider.

XText 2.9 generates the following scope provider code for you (in MyDslScopeProvider.xtend):

class MyDslScopeProvider extends AbstractMyDslScopeProvider {
}

AbstractMyDslScopeProvider has no methods of it's own, it just inherits from DelegatingScopeProvider.

I can't wrap my head around how this works or where the code for the scope lookup should go. The "documentation" doesn't really help, because there's only useless code snippets instead of a complete working example.

Earlier versions of XText used AbstractDeclarativeScopeProvider and that was quite easy to understand and use, pre 2.9 it would have been:

class MyDslScopeProvider extends AbstractDeclarativeScopeProvider {
    def IScope scope_Reference_stuff(Reference reference, EReference ref) {
        scopeFor(reference?.thing.stuff)
    }
}

Solution

  • You need to implement the getScope method

    override getScope(EObject ctx, EReference ref) {
       if (ref == MyDslPackage.Literals.REFERENCE_THING) {
          return createScopeForThings()
       } else if (ref == MyDslPackage.Literals.REFERENCE_STUFF) {
          return createScopeForStuff()
       }
    }
    

    In your case you will get a call where the EObject is an instanceof Reference and the EReference is either MyDslPackage.Literals.REFERENCE_THING or MyDslPackage.Literals.REFERENCE_STUFF.

    You need to create and return an instance of IScope, which can be used by the linker and content assist. See the JavaDoc of IScopeProvider and IScope for more details.