Couldn't resolve reference in DSL using Xtext [message #1810568] |
Tue, 13 August 2019 14:38 |
Loredana Hozan Messages: 34 Registered: January 2019 |
Member |
|
|
Hi,
i have this grammar:
grammar org.xtext.example.mydsl.MyDsl with org.eclipse.xtext.common.Terminals
generate myDsl
Root:
'root' name=ROOT_FQN ('extends' parentRoot=[Root|ROOT_FQN])? '{'
('Values-Catalog' '{'
values+=(Values)*
'}')?
('Models-Catalog' '{'
models+=(Model)*)?
'}'
'}';
Values:
StringValue | ModelValue;
StringValue:
name=ID type='string' (array?='[' length=INT ']')?;
ModelValue:
name=ID type=[Model|MODEL_FQN] (description=STRING)? ;
Model:
type=('data' | 'static')? name=ID ('extends' parentModel=[Model|MODEL_FQN])? '{'
data+=Data*
'}';
Data:
name=ID;
terminal VERSION:
INT '.' INT '.' INT;
terminal ROOT_FQN:
ID '-' VERSION;
terminal MODEL_FQN:
ROOT_FQN '.' ID;
The root should be able to have a parent root. A value can be a simple type or a model from the current root or it's parents. A model can have a parent model from the current root or it's parents. With this grammar i can extend another model and crate a model value using a model from any root that is in the workspace without having the reference issue. I have wrote a scope provider that will limit the models to the ones from the current root or it's parents. I get the right list of models in the context menu but when want to extend a model and select one from the list i get 'Couldn't resolve a reference to rootName.modelName', however when i try to create a value using a model from the same restricted list i don't get any errors. Here's the scope provider:
class MyDslScopeProvider extends AbstractMyDslScopeProvider {
val ePackage = MyDslPackage.eINSTANCE
override getScope(EObject context,EReference reference){
if(reference == ePackage.model_ParentModel){
return scopeForParentModel(context as Model, reference)
}
if(reference == ePackage.values){
return scopeForValueParentModel(context,reference);
}
return super.getScope(context, reference)
}
//scope for the parent of a model
def protected IScope scopeForParentModel(Model context, EReference reference) {
val container=context.eContainer as Root;
val List<Model> models=newArrayList;
setModels(container, models);
return Scopes::scopeFor(models, [QualifiedName.create((it.eContainer as Root).name , it.name)],IScope.NULLSCOPE) [img]index.php/fa/36091/0/[/img]
}
//scope for model values
def protected IScope scopeForValueParentModel(EObject context, EReference reference) {
val container = context as Root
val List<Model> entities = newArrayList;
setModels(container, entities);
return Scopes::scopeFor(entities, [QualifiedName.create((it.eContainer as Root).name, it.name)],
IScope.NULLSCOPE);
}
//recursive method that will store all the models from the root hierarchy in the models list
def protected void setModels(Root context, List<Model> models) {
models.addAll(context.models);
if (context.parentRoot !== null) {
setModels(context.parentRoot, models);
}
}
}
As i have looked through similar topics and question online i have created a simple QualifiedNameProvider and one using a converter ( converter.toQualifiedName(object.eContainer.fullyQualifiedName + "." + object.name) , and i bound it to the runtime module ) but i still get the reference error, any suggestions?
|
|
|
Re: Couldn't resolve reference in DSL using Xtext [message #1810636 is a reply to message #1810568] |
Wed, 14 August 2019 20:19 |
|
you create Qualified Names with
QualifiedName.create
in this case you have to make sure the segments are correct (dont contain .)
as you have already found out you can use qualfied name converter for that
(or make sure otherwise e.g.)
def protected IScope scopeForParentModel(Model context, EReference reference) {
val container=context.eContainer as Root;
val List<Model> models=newArrayList;
setModels(container, models);
return Scopes::scopeFor(models, [
QualifiedName.create((it.eContainer as Root).name.split("\\.")).append(it.name)
],IScope.NULLSCOPE)
}
or
def protected IScope scopeForParentModel(Model context, EReference reference) {
val container=context.eContainer as Root;
val List<Model> models=newArrayList;
setModels(container, models);
return Scopes::scopeFor(models, [
converter.toQualifiedName((it.eContainer as Root).name + "."+it.name)
],IScope.NULLSCOPE)
}
@Inject
IQualifiedNameConverter converter
Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
|
|
|
|
Powered by
FUDForum. Page generated in 0.03158 seconds