@@ -11,88 +11,100 @@ import org.eclipse.xtext.nodemodel.util.NodeModelUtils
11
11
import org.eclipse.emf.ecore.EObject
12
12
import org.eclipse.xtext.diagnostics.IDiagnosticConsumer
13
13
import org.eclipse.xtext.resource.impl.ListBasedDiagnosticConsumer
14
- import java.util.Map
15
- import org.eclipse.xtext.diagnostics.IDiagnosticProducer
16
14
import org.eclipse.xtext.nodemodel.INode
17
15
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
25
16
import org.eclipse.xtext.diagnostics.Severity
26
17
import org.eclipse.xtext.naming.QualifiedName
27
- import org.eclipse.xtext.linking.ILinkingDiagnosticMessageProvider
28
- import org.eclipse.xtext.linking.impl.Linker
29
18
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
33
19
import java.util.Collection
34
- import java.util.Collections
35
20
import com.regnosys.rosetta.scoping.RosettaScopeProvider
36
21
import org.eclipse.emf.ecore.resource.Resource
37
22
import org.eclipse.xtext.scoping.IScope
38
23
import com.regnosys.rosetta.rosetta.RosettaModel
39
24
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
40
38
41
39
class ExpressionParser {
42
40
@Inject IParser parser
43
41
@Inject RosettaGrammarAccess grammar
42
+ @Inject ModelHelper modelHelper
43
+ @Inject Provider<XtextResource > resourceProvider
44
44
@Inject RosettaStaticLinker linker
45
45
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
-
58
46
def RosettaExpression parseExpression (CharSequence expr ) {
59
- return parseExpression(expr, Collections . emptyList)
47
+ return parseExpression(expr, emptyList)
60
48
}
61
49
62
50
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)
65
57
}
66
58
67
59
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 ) {
68
64
val IParseResult result = parser. parse(grammar. rosettaCalcExpressionRule, new StringReader (expr. toString()))
69
65
assertFalse(result. hasSyntaxErrors)
70
66
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)
72
70
return expression
73
71
}
74
72
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)
79
75
}
80
76
81
- def Attribute createAttribute (CharSequence attr ) {
77
+ def Attribute createAttribute (CharSequence attr , List< RosettaModel > context ) {
82
78
val IParseResult result = parser. parse(grammar. attributeRule, new StringReader (attr. toString()))
83
79
assertFalse(result. hasSyntaxErrors)
84
80
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 ])
88
100
}
89
101
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)
92
104
val consumer = new ListBasedDiagnosticConsumer
93
105
linker. linkModel(obj, consumer)
94
106
95
- val errors = consumer. getResult(Severity . ERROR )
107
+ val errors = consumer. getResult(Severity . ERROR ) + obj . eResource . errors
96
108
val warnings = consumer. getResult(Severity . WARNING )
97
109
if (! errors. empty) {
98
110
throw new RuntimeException (errors. toString)
@@ -102,98 +114,82 @@ class ExpressionParser {
102
114
}
103
115
}
104
116
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
109
119
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
113
122
}
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
124
126
}
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))
127
130
}
128
131
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));
135
148
}
136
- clearGlobals
149
+ return result;
137
150
}
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)
140
154
}
155
+ }
156
+ private static class RosettaStaticLinker extends LazyLinker {
157
+ @Inject
158
+ RosettaContextBasedScopeProvider scopeProvider
159
+
160
+ IScope staticScope = IScope . NULLSCOPE
141
161
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)
147
165
}
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
177
169
}
178
170
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 ) {
180
181
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)
189
187
} else {
190
- producer . addDiagnostic(linkingDiagnosticMessageProvider . getUnresolvedProxyMessage(createDiagnosticContext(obj, eRef, node)))
188
+ obj . eSet( eRef, resolved);
191
189
}
190
+ } else {
191
+ super . createAndSetProxy(obj, node, eRef)
192
192
}
193
193
}
194
-
195
- protected def boolean hasLeafNodes (INode node ) {
196
- return ! Iterables . isEmpty(node. getLeafNodes());
197
- }
198
194
}
199
195
}
0 commit comments