I am having trouble with this concept in building a dsl. I am not sure if it is a simple thing I am missing or something that is not an intended feature of xtext. Hopefully someone can explain it to me in the context of this example.
Given the following minimal grammar:
Model:
'ns' name=QualifiedName
classes+=Class*
instances+=Instance*
uses+=Use*
;
Class:
'class' name=ID '{'
variables+=Variable*
'}'
;
Variable:
'var' variable=PrimaryVariable
;
Instance:
variable=PrimaryVariable '=' 'new' type=[Class]
;
Use:
reference=[PrimaryVariable|QualifiedName]
;
PrimaryVariable:
name=ID
;
QualifiedName:
ID ('.' ID)*
;
I would like to be able to write the following code, which of course is not valid:
ns com.mine
class Class1 {
var var1
}
instance1 = new Class1
instance1.var1 // <- error here, can't resolve reference
With this grammar and default scoping, only this would work:
ns com.mine
class Class1 {
var var1
}
instance1 = new Class1
Class1.var1
So my question is: how would I go about implementing the concept of referencing variables by qualified name through an instance variable?
I don't think I could manage qualifiedNameProvider
to achieve this because the PrimaryVariable
does not have knowledge of what instance it is being used in.
I could of course create a rule which uses two reference (and is what I am currently doing), one to the instance variable and then traverse the instance variable's type to get variables in scope for the variable reference, but this seems like a hack to the way it should be and not as scalable in the case of nested objects.
This is a slightly broad question, I am hoping that I can get informed before I go off doing something completely counter productive.
Here is a sample for the scope provider
import org.eclipse.emf.ecore.EObject
import org.eclipse.emf.ecore.EReference
import org.eclipse.xtext.EcoreUtil2
import org.eclipse.xtext.naming.QualifiedName
import org.eclipse.xtext.resource.EObjectDescription
import org.eclipse.xtext.scoping.IScope
import org.eclipse.xtext.scoping.impl.SimpleScope
import org.xtext.example.mydsl6.myDsl.Model
import org.xtext.example.mydsl6.myDsl.MyDslPackage
class MyDslScopeProvider extends AbstractMyDslScopeProvider {
override getScope(EObject context, EReference reference) {
if (reference === MyDslPackage.Literals.USE__REFERENCE) {
val model = EcoreUtil2.getContainerOfType(context, Model)
if (model !== null) {
val result = newArrayList
for (i : model.instances) {
result.add( EObjectDescription.create(
QualifiedName.create( i.variable.name ), i.variable ))
for (v : i.type.variables) {
result.add( EObjectDescription.create(
QualifiedName.create( i.variable.name, v.variable.name ),
v.variable ))
}
}
println(result)
return new SimpleScope(IScope.NULLSCOPE, result)
}
}
super.getScope(context, reference)
}
}