问题
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)
}
}
回答1:
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.
来源:https://stackoverflow.com/questions/36224089/xtext-2-9-scope-provider