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)
}
}
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With