I am struggling to cross-reference via the name of a function parameter in a function definition, and battling to Google the solution. Consider following example.
def helloWorld() {
return "Hello World!"
}
def combine(Person person, Place place) {
return person.name + place.code // ❎ Couldn't resolve reference to Feature 'name'.
}
entity Person {
name: String
title : String
occupation : String
}
entity Place {
name: String
code:String
}
datatype String
The grammar is the following, which extends the standard example with a very simple notion of function definition via a simple expression language.
grammar org.xtext.example.mydsl.MyDsl with org.eclipse.xtext.common.Terminals
generate myDsl "http://www.xtext.org/example/mydsl/MyDsl"
Domainmodel :
(
elements+=Type |
functions+=Function // Note Functions
)*;
/******************** Functions ********************/
Function : 'def' name=ID '('
(parameters+=Parameter (',' parameters+=Parameter)*)?
')' '{' 'return' exp=Exp '}'
;
Parameter: type=[Entity] name=ID;
Exp:
TerminalExp
({Exp.left=current}
'+'
right=TerminalExp)*;
TerminalExp : value=STRING | dotExpression = DotExpression;
/******************** PROBLEM AREA ********************/
DotExpression : parameterRef=[Parameter] '.' featureRef=FeatureRef;
FeatureRef : featureRef=[Feature];
/******************** THE USUAL ********************/
Type:
DataType | Entity;
DataType:
'datatype' name=ID;
Entity:
'entity' name=ID '{'
(features+=Feature)*
'}';
Feature:
name=ID ':' type=[Type];
This grammar parses perfectly, but the dotted use of a function parameter name is not linking properly. My scope provider is the following, the latter exception throwing method concerns a secondary issue.
/*
* generated by Xtext 2.14.0
*/
package org.xtext.example.mydsl.scoping
import org.eclipse.emf.ecore.EObject
import org.eclipse.emf.ecore.EReference
import org.eclipse.xtext.scoping.IScope
import org.eclipse.xtext.scoping.Scopes
import org.xtext.example.mydsl.myDsl.DotExpression
import org.xtext.example.mydsl.myDsl.FeatureRef
class MyDslScopeProvider extends AbstractMyDslScopeProvider {
override getScope(EObject context, EReference reference) {
if (context instanceof FeatureRef) {
val myDotExpression = (context as EObject/*?*/).eContainer as DotExpression
val features = myDotExpression.parameterRef.type.features
println("### " + features.stream.map["[" + name + "]"].reduce("", [$0 + $1]))
Scopes::scopeFor(features)
}
super.getScope(context, reference)
}
def IScope scope_FeatureRef(FeatureRef context, EReference ref) {
println("### I have been called")
throw new RuntimeException("I HAVE BEEN CALLED!");
}
}
The following output demonstrates that (1) the correct objects are found and that they have then expected names, and (2) that the latter method is never called.
### [name][title][occupation]
### [name][code]
### [name][title][occupation]
### [name][code]
- What mistake am I making in in the first scope method?
- Why is the latter method never called?
I have read Xtext and Dot/Path-Expressions and Runtime Concepts:Scoping. I have also seen the solution before, but have tried unsuccessfully for days to Google it.