Skip to content

Commit 34e25ad

Browse files
author
Diana Şutac
committed
Added Simon's changes
1 parent 0659dd1 commit 34e25ad

File tree

4 files changed

+190
-121
lines changed

4 files changed

+190
-121
lines changed

rosetta-lang/src/main/java/com/regnosys/rosetta/scoping/RosettaScopeProvider.xtend

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -252,12 +252,12 @@ class RosettaScopeProvider extends ImportedNamespaceAwareLocalScopeProvider {
252252
}
253253

254254
private def IScope defaultScope(EObject object, EReference reference) {
255-
filteredScope(super.getScope(object,reference), [it.EClass !== FUNCTION_DISPATCH])
255+
filteredScope(super.getScope(object, reference), [it.EClass !== FUNCTION_DISPATCH])
256256
}
257257

258258
private def IScope getSymbolParentScope(EObject object, EReference reference, IScope outer) {
259-
if (object === null) {
260-
return IScope.NULLSCOPE
259+
if (object.eContainer === null) {
260+
return defaultScope(object, reference)
261261
}
262262
val parentScope = getSymbolParentScope(object.eContainer, reference, outer)
263263
switch (object) {

rosetta-testing/src/main/java/com/regnosys/rosetta/tests/util/ExpressionParser.xtend

Lines changed: 114 additions & 118 deletions
Original file line numberDiff line numberDiff line change
@@ -11,88 +11,100 @@ import org.eclipse.xtext.nodemodel.util.NodeModelUtils
1111
import org.eclipse.emf.ecore.EObject
1212
import org.eclipse.xtext.diagnostics.IDiagnosticConsumer
1313
import org.eclipse.xtext.resource.impl.ListBasedDiagnosticConsumer
14-
import java.util.Map
15-
import org.eclipse.xtext.diagnostics.IDiagnosticProducer
1614
import org.eclipse.xtext.nodemodel.INode
1715
import org.eclipse.emf.ecore.EReference
18-
import org.eclipse.xtext.CrossReference
19-
import org.eclipse.xtext.nodemodel.ICompositeNode
20-
import org.eclipse.xtext.RuleCall
21-
import org.eclipse.xtext.ParserRule
22-
import org.eclipse.xtext.GrammarUtil
23-
import com.google.common.collect.Iterables
24-
import org.eclipse.xtext.linking.impl.LinkingDiagnosticProducer
2516
import org.eclipse.xtext.diagnostics.Severity
2617
import org.eclipse.xtext.naming.QualifiedName
27-
import org.eclipse.xtext.linking.ILinkingDiagnosticMessageProvider
28-
import org.eclipse.xtext.linking.impl.Linker
2918
import com.regnosys.rosetta.rosetta.simple.Attribute
30-
import com.regnosys.rosetta.builtin.RosettaBuiltinsService
31-
import org.eclipse.emf.ecore.resource.ResourceSet
32-
import com.regnosys.rosetta.rosetta.RosettaType
3319
import java.util.Collection
34-
import java.util.Collections
3520
import com.regnosys.rosetta.scoping.RosettaScopeProvider
3621
import org.eclipse.emf.ecore.resource.Resource
3722
import org.eclipse.xtext.scoping.IScope
3823
import com.regnosys.rosetta.rosetta.RosettaModel
3924
import javax.inject.Inject
25+
import java.util.List
26+
import com.google.common.base.Predicate
27+
import org.eclipse.xtext.resource.IEObjectDescription
28+
import org.eclipse.xtext.scoping.Scopes
29+
import static java.util.Collections.singletonList
30+
import org.eclipse.xtext.linking.lazy.LazyLinker
31+
import javax.inject.Provider
32+
import org.eclipse.xtext.resource.XtextResource
33+
import org.eclipse.emf.common.util.URI
34+
import org.eclipse.xtext.EcoreUtil2
35+
import org.eclipse.emf.ecore.util.InternalEList
36+
import org.eclipse.xtext.linking.lazy.LazyLinkingResource
37+
import org.eclipse.xtext.linking.impl.DefaultLinkingService
4038

4139
class ExpressionParser {
4240
@Inject IParser parser
4341
@Inject RosettaGrammarAccess grammar
42+
@Inject ModelHelper modelHelper
43+
@Inject Provider<XtextResource> resourceProvider
4444
@Inject RosettaStaticLinker linker
4545

46-
Map<String, ? extends EObject> basicTypes
47-
48-
@Inject
49-
new(RosettaBuiltinsService builtins, ResourceSet resourceSet) {
50-
resourceSet.getResource(builtins.basicTypesURI, true).getContents().get(0) as RosettaModel => [
51-
basicTypes = elements
52-
.filter[it instanceof RosettaType]
53-
.map[it as RosettaType]
54-
.toMap[name]
55-
]
56-
}
57-
5846
def RosettaExpression parseExpression(CharSequence expr) {
59-
return parseExpression(expr, Collections.emptyList)
47+
return parseExpression(expr, emptyList)
6048
}
6149

6250
def RosettaExpression parseExpression(CharSequence expr, Collection<? extends CharSequence> attrs) {
63-
val attributes = attrs.map[createAttribute].toList
64-
return parseExpression(expr, attributes)
51+
return parseExpression(expr, defaultContext, attrs)
52+
}
53+
54+
def RosettaExpression parseExpression(CharSequence expr, List<RosettaModel> context, Collection<? extends CharSequence> attrs) {
55+
val attributes = attrs.map[createAttribute(context)].toList
56+
return parseExpression(expr, context, attributes)
6557
}
6658

6759
def RosettaExpression parseExpression(CharSequence expr, Attribute... attributes) {
60+
return parseExpression(expr, defaultContext, attributes)
61+
}
62+
63+
def RosettaExpression parseExpression(CharSequence expr, List<RosettaModel> context, Attribute... attributes) {
6864
val IParseResult result = parser.parse(grammar.rosettaCalcExpressionRule, new StringReader(expr.toString()))
6965
assertFalse(result.hasSyntaxErrors)
7066
val expression = result.rootASTElement as RosettaExpression
71-
linkVariables(expression, attributes)
67+
val exprRes = createResource("expr", expression, context)
68+
link(expression, context, attributes)
69+
deleteResource(exprRes, context)
7270
return expression
7371
}
7472

75-
private def void linkVariables(EObject obj, Collection<Attribute> attrs) {
76-
val attributeMap = attrs
77-
.toMap[name]
78-
link(obj, attributeMap)
73+
def Attribute createAttribute(CharSequence attr) {
74+
return createAttribute(attr, defaultContext)
7975
}
8076

81-
def Attribute createAttribute(CharSequence attr) {
77+
def Attribute createAttribute(CharSequence attr, List<RosettaModel> context) {
8278
val IParseResult result = parser.parse(grammar.attributeRule, new StringReader(attr.toString()))
8379
assertFalse(result.hasSyntaxErrors)
8480
val attribute = result.rootASTElement as Attribute
85-
86-
link(attribute, basicTypes)
87-
attribute
81+
val attrRes = createResource("attribute " + attr, attribute, context)
82+
link(attribute, context, emptyList)
83+
deleteResource(attrRes, context)
84+
return attribute
85+
}
86+
87+
private def Resource createResource(String name, EObject content, List<RosettaModel> context) {
88+
val resource = resourceProvider.get()
89+
resource.URI = URI.createURI("synthetic://" + name)
90+
resource.contents.add(content)
91+
context.head.eResource.resourceSet.resources.add(resource)
92+
resource
93+
}
94+
private def void deleteResource(Resource resource, List<RosettaModel> context) {
95+
context.head.eResource.resourceSet.resources.remove(resource)
96+
}
97+
98+
private def List<RosettaModel> defaultContext() {
99+
return newArrayList(modelHelper.testResourceSet.resources.map[contents.head as RosettaModel])
88100
}
89101

90-
private def void link(EObject obj, Map<String, ? extends EObject> globals) {
91-
linker.setGlobalsForNextLink(globals)
102+
private def void link(EObject obj, List<RosettaModel> context, Collection<? extends EObject> globals) {
103+
linker.setStateForNextLink(context, globals)
92104
val consumer = new ListBasedDiagnosticConsumer
93105
linker.linkModel(obj, consumer)
94106

95-
val errors = consumer.getResult(Severity.ERROR)
107+
val errors = consumer.getResult(Severity.ERROR) + obj.eResource.errors
96108
val warnings = consumer.getResult(Severity.WARNING)
97109
if (!errors.empty) {
98110
throw new RuntimeException(errors.toString)
@@ -102,98 +114,82 @@ class ExpressionParser {
102114
}
103115
}
104116

105-
private static class RosettaNullResourceScopeProvider extends RosettaScopeProvider {
106-
override protected IScope getResourceScope(Resource res, EReference reference) {
107-
return IScope.NULLSCOPE
108-
}
117+
private static class RosettaContextBasedScopeProvider extends RosettaScopeProvider {
118+
List<RosettaModel> context = emptyList
109119

110-
override protected IScope getLocalElementsScope(IScope parent, EObject context,
111-
EReference reference) {
112-
return parent
120+
def void setContext(List<RosettaModel> context) {
121+
this.context = context
113122
}
114-
}
115-
private static class RosettaStaticLinker extends Linker {
116-
@Inject
117-
RosettaNullResourceScopeProvider scopeProvider
118-
@Inject
119-
ILinkingDiagnosticMessageProvider linkingDiagnosticMessageProvider
120-
Map<String, ? extends EObject> globals = newHashMap
121-
122-
def void setGlobalsForNextLink(Map<String, ? extends EObject> globals) {
123-
this.globals = globals
123+
124+
override protected getImplicitImports(boolean ignoreCase) {
125+
(super.getImplicitImports(ignoreCase) + context.map[name].toSet.map[createImportedNamespaceResolver(it + ".*", ignoreCase)]).toList
124126
}
125-
private def void clearGlobals() {
126-
globals = newHashMap
127+
128+
override protected IScope getResourceScope(Resource res, EReference reference) {
129+
return createImportScope(getGlobalScope(this.context.head.eResource, reference), getImplicitImports(isIgnoreCase(reference)), null, reference.getEReferenceType(), isIgnoreCase(reference))
127130
}
128131

129-
override protected doLinkModel(EObject root, IDiagnosticConsumer consumer) {
130-
val producer = new LinkingDiagnosticProducer(consumer);
131-
val iterator = getAllLinkableContents(root)
132-
while (iterator.hasNext()) {
133-
val eObject = iterator.next();
134-
installLinks(eObject, producer);
132+
override protected IScope getLocalElementsScope(IScope parent, EObject context, EReference reference) {
133+
var result = parent;
134+
val allDescriptions = getAllDescriptions(this.context.head.eResource);
135+
val name = getQualifiedNameOfLocalElement(context);
136+
val ignoreCase = isIgnoreCase(reference);
137+
val namespaceResolvers = getImportedNamespaceResolvers(context, ignoreCase);
138+
if (!namespaceResolvers.isEmpty()) {
139+
if (isRelativeImport() && name!==null && !name.isEmpty()) {
140+
val localNormalizer = doCreateImportNormalizer(name, true, ignoreCase);
141+
result = createImportScope(result, singletonList(localNormalizer), allDescriptions, reference.getEReferenceType(), isIgnoreCase(reference));
142+
}
143+
result = createImportScope(result, namespaceResolvers, null, reference.getEReferenceType(), isIgnoreCase(reference));
144+
}
145+
if (name!==null) {
146+
val localNormalizer = doCreateImportNormalizer(name, true, ignoreCase);
147+
result = createImportScope(result, singletonList(localNormalizer), allDescriptions, reference.getEReferenceType(), isIgnoreCase(reference));
135148
}
136-
clearGlobals
149+
return result;
137150
}
138-
override void beforeModelLinked(EObject model, IDiagnosticConsumer diagnosticsConsumer) {
139-
151+
152+
override protected getGlobalScope(Resource context, EReference reference, Predicate<IEObjectDescription> filter) {
153+
super.getGlobalScope(this.context.head.eResource, reference, filter)
140154
}
155+
}
156+
private static class RosettaStaticLinker extends LazyLinker {
157+
@Inject
158+
RosettaContextBasedScopeProvider scopeProvider
159+
160+
IScope staticScope = IScope.NULLSCOPE
141161

142-
protected def void installLinks(EObject obj, IDiagnosticProducer producer) {
143-
val node = NodeModelUtils.getNode(obj);
144-
if (node === null)
145-
return;
146-
installLinks(obj, producer, node, false);
162+
def void setStateForNextLink(List<RosettaModel> context, Collection<? extends EObject> globals) {
163+
scopeProvider.setContext(context)
164+
staticScope = Scopes.scopeFor(globals)
147165
}
148-
149-
private def void installLinks(EObject obj, IDiagnosticProducer producer, ICompositeNode parentNode, boolean dontCheckParent) {
150-
val eClass = obj.eClass();
151-
if (eClass.EAllReferences.size - eClass.EAllContainments.size === 0)
152-
return;
153-
154-
for (var node = parentNode.firstChild; node !== null; node = node.nextSibling) {
155-
val grammarElement = node.grammarElement
156-
if (grammarElement instanceof CrossReference && hasLeafNodes(node)) {
157-
producer.setNode(node);
158-
val crossReference = grammarElement as CrossReference;
159-
val eRef = GrammarUtil.getReference(crossReference, eClass);
160-
if (eRef === null) {
161-
val parserRule = GrammarUtil.containingParserRule(crossReference);
162-
val feature = GrammarUtil.containingAssignment(crossReference).getFeature();
163-
throw new IllegalStateException("Couldn't find EReference for crossreference '"+eClass.getName()+"::"+feature+"' in parser rule '"+parserRule.getName()+"'.");
164-
}
165-
setLink(obj, node, eRef, producer);
166-
} else if (grammarElement instanceof RuleCall && node instanceof ICompositeNode) {
167-
val ruleCall = grammarElement as RuleCall;
168-
val calledRule = ruleCall.getRule();
169-
if (calledRule instanceof ParserRule && (calledRule as ParserRule).isFragment()) {
170-
installLinks(obj, producer, node as ICompositeNode, true);
171-
}
172-
}
173-
}
174-
if (!dontCheckParent && shouldCheckParentNode(parentNode)) {
175-
installLinks(obj, producer, parentNode.getParent(), dontCheckParent);
176-
}
166+
private def void clearState() {
167+
scopeProvider.setContext(emptyList)
168+
staticScope = IScope.NULLSCOPE
177169
}
178170

179-
private def void setLink(EObject obj, INode node, EReference eRef, IDiagnosticProducer producer) {
171+
override protected doLinkModel(EObject root, IDiagnosticConsumer consumer) {
172+
// TODO: this is hacky
173+
((root.eResource as LazyLinkingResource).linkingService as DefaultLinkingService).setScopeProvider(scopeProvider)
174+
175+
super.doLinkModel(root, consumer)
176+
EcoreUtil2.resolveAll(root)
177+
clearState
178+
}
179+
180+
protected override void createAndSetProxy(EObject obj, INode node, EReference eRef) {
180181
val varName = NodeModelUtils.getTokenText(node)
181-
val scope = scopeProvider.getScope(obj, eRef)
182-
val elementInScope = scope.getSingleElement(QualifiedName.create(varName))
183-
if (elementInScope !== null) {
184-
obj.eSet(eRef, elementInScope)
185-
} else {
186-
val elementInGlobals = globals.get(varName)
187-
if (elementInGlobals !== null) {
188-
obj.eSet(eRef, elementInGlobals)
182+
val staticElement = staticScope.getSingleElement(QualifiedName.create(varName))
183+
if (staticElement !== null) {
184+
val resolved = staticElement.getEObjectOrProxy()
185+
if (eRef.isMany()) {
186+
(obj.eGet(eRef, false) as InternalEList<EObject>).addUnique(resolved)
189187
} else {
190-
producer.addDiagnostic(linkingDiagnosticMessageProvider.getUnresolvedProxyMessage(createDiagnosticContext(obj, eRef, node)))
188+
obj.eSet(eRef, resolved);
191189
}
190+
} else {
191+
super.createAndSetProxy(obj, node, eRef)
192192
}
193193
}
194-
195-
protected def boolean hasLeafNodes(INode node) {
196-
return !Iterables.isEmpty(node.getLeafNodes());
197-
}
198194
}
199195
}

rosetta-testing/src/test/java/com/regnosys/rosetta/interpreternew/RosettaInterpreterConditionalExpressionTest.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,11 @@
2424
import com.regnosys.rosetta.rosetta.interpreter.RosettaInterpreterValue;
2525
import com.regnosys.rosetta.tests.RosettaInjectorProvider;
2626
import com.regnosys.rosetta.tests.util.ExpressionParser;
27+
import com.regnosys.rosetta.tests.util.ModelHelper;
2728
import com.rosetta.model.lib.RosettaNumber;
2829

30+
import com.regnosys.rosetta.rosetta.RosettaModel;
31+
2932
@ExtendWith(InjectionExtension.class)
3033
@InjectWith(RosettaInjectorProvider.class)
3134
public class RosettaInterpreterConditionalExpressionTest {
@@ -36,6 +39,10 @@ public class RosettaInterpreterConditionalExpressionTest {
3639
@Inject
3740
RosettaInterpreterNew interpreter;
3841

42+
@Inject
43+
ModelHelper mh;
44+
45+
3946
@Test
4047
public void integerTest() {
4148
RosettaExpression expr = parser.parseExpression("if True then 1");
@@ -220,5 +227,15 @@ public void noElseTest() {
220227

221228
assertEquals(null, result);
222229
}
230+
231+
@Test
232+
public void test() {
233+
RosettaModel expr = mh.parseRosettaWithNoErrors("recordType date\r\n"
234+
+ "{\r\n"
235+
+ " day int\r\n"
236+
+ " month int\r\n"
237+
+ " year int }");
238+
System.out.println(expr.getElements().get(0).getClass());
239+
}
223240

224241
}

0 commit comments

Comments
 (0)