Я изо всех сил пытаюсь сделать перекрестную ссылку через имя параметра функции в определении функции, и сражаются с Google решением. Рассмотрим следующий пример.
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
Грамматика является следующей, которая расширяет стандартный пример с очень простым понятием функции определение через простой язык выражений.
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];
Эта грамматика отлично разбирается, но пунктирное использование имени параметра функции не связывает должным образом. Мой провайдер контекста следующий, последний метод создания исключений касается вторичной проблемы.
/*
* 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!");
}
}
Следующий вывод демонстрирует, что (1) найдены правильные объекты и что они имеют ожидаемые имена, и (2) что последний метод никогда не вызывается.
### [name][title][occupation]
### [name][code]
### [name][title][occupation]
### [name][code]
- Какую ошибку я совершаю в первом методе области видимости?
- Почему последний метод никогда не вызывается?
Я прочитал Выражения Xtext и Dot / Path и Концепции времени выполнения: Scoping . Я также видел решение раньше, но несколько дней безуспешно пытался его найти.