Skip to content

Commit b2c8c72

Browse files
committed
ST6RI-728 Updated KerMLScope to properly handle cross-redefinitions.
1 parent aa72c30 commit b2c8c72

1 file changed

Lines changed: 30 additions & 26 deletions

File tree

org.omg.kerml.xtext/src/org/omg/kerml/xtext/scoping/KerMLScope.xtend

Lines changed: 30 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*****************************************************************************
22
* SysML 2 Pilot Implementation
33
* Copyright (c) 2018 IncQuery Labs Ltd.
4-
* Copyright (c) 2018-2022,2024 Model Driven Solutions, Inc.
4+
* Copyright (c) 2018-2022, 2024, 2025 Model Driven Solutions, Inc.
55
* Copyright (c) 2018-2020 California Institute of Technology/Jet Propulsion Laboratory
66
*
77
* This program is free software: you can redistribute it and/or modify
@@ -123,9 +123,9 @@ class KerMLScope extends AbstractScope implements ISysMLScope {
123123
protected QualifiedName targetqn;
124124

125125
/**
126-
* A map of Elements to the QualifiedNames found for them in the scope.
126+
* A map of QualifiedNames to the Elements resolved for them in the scope.
127127
*/
128-
protected Map<Element, Set<QualifiedName>> elements
128+
protected Map<QualifiedName, Set<Element>> elements
129129

130130
/**
131131
* The QualifiedNames that have already been seen during a resolution search.
@@ -200,8 +200,8 @@ class KerMLScope extends AbstractScope implements ISysMLScope {
200200
this.elements = newHashMap
201201
this.visitedqns = newHashSet
202202
resolve()
203-
elements.keySet.flatMap[key |
204-
elements.get(key).map[qn | EObjectDescription.create(qn, key)]
203+
elements.keySet.flatMap[qn |
204+
elements.get(qn).map[elm | EObjectDescription.create(qn, elm)]
205205
]
206206
}
207207

@@ -231,18 +231,22 @@ class KerMLScope extends AbstractScope implements ISysMLScope {
231231
}
232232

233233
protected def boolean addName(QualifiedName qn, Membership mem, Element elm) {
234-
var el = elm
235-
if (referenceType !== SysMLPackage.eINSTANCE.membership && !referenceType.isInstance(el)) {
234+
if (referenceType !== SysMLPackage.eINSTANCE.membership && !referenceType.isInstance(elm)) {
236235
return false
237236
} else {
238-
if (findFirst && referenceType === SysMLPackage.eINSTANCE.membership) {
239-
el = mem
240-
}
241-
val qns = elements.get(el)
242-
if (qns === null) {
243-
elements.put(el, newHashSet(qn))
237+
val el = if (findFirst && referenceType === SysMLPackage.eINSTANCE.membership) mem else elm
238+
val elms = elements.get(qn)
239+
if (elms === null) {
240+
elements.put(qn, newHashSet(el))
241+
} else if (findFirst && el instanceof Feature) {
242+
// If findFirst = true then the only time multiple elements will be added for the same qualified
243+
// name is during the traversal of general types. In this case, the chosen element should be one
244+
// that is not redefined by any other element for the qualified name.
245+
if (elms.exists[old | FeatureUtil.getAllRedefinedFeaturesOf(el as Feature).contains(old)]) {
246+
elements.put(qn, newHashSet(el))
247+
}
244248
} else {
245-
qns.add(qn)
249+
elms.add(el)
246250
}
247251
return true
248252
}
@@ -326,13 +330,8 @@ class KerMLScope extends AbstractScope implements ISysMLScope {
326330
protected def addQualifiedName(QualifiedName elementqn, Membership mem, Element memberElement) {
327331
visitedqns.add(elementqn)
328332
if (targetqn === null || targetqn == elementqn) {
329-
if (addName(elementqn, mem, memberElement)) {
330-
if (targetqn != elementqn && memberElement instanceof Namespace) {
331-
isShadowing = true
332-
}
333-
if (findFirst && targetqn == elementqn) {
334-
return true
335-
}
333+
if (addName(elementqn, mem, memberElement) && findFirst && targetqn !== null) {
334+
return true;
336335
}
337336
}
338337
false
@@ -358,6 +357,7 @@ class KerMLScope extends AbstractScope implements ISysMLScope {
358357
}
359358

360359
protected def boolean gen(Namespace ns, QualifiedName qn, Set<Namespace> visited, Set<Element> redefined, boolean isInheriting, boolean includeImplicit) {
360+
var isFound = false
361361
if (ns instanceof Type) {
362362
val conjugator = ns.ownedConjugator
363363
if (conjugator !== null && !scopeProvider.visited.contains(conjugator)) {
@@ -373,15 +373,19 @@ class KerMLScope extends AbstractScope implements ISysMLScope {
373373
newRedefined.addAll(redefined)
374374
newRedefined.addAll(TypeUtil.getFeaturesRedefinedBy(ns, skip))
375375
}
376+
377+
// Note: All specializations are traversed, even if a resolution is found, in order to check for possible redefinitions inherited
378+
// from subsequent specializations. If findFirst = true, the selection of a single element is handled in addName.
379+
376380
for (e: ns.ownedSpecialization) {
377381
if (!scopeProvider.visited.contains(e)) {
378-
// NOTE: Exclude the generalization e to avoid possible circular name resolution
382+
// NOTE: Exclude the specialization e to avoid possible circular name resolution
379383
// when resolving a proxy for e.general.
380384
scopeProvider.addVisited(e)
381385
val found = e.general.resolveIfUnvisited(qn, false, visited, newRedefined, isInheriting, false, includeImplicit, false)
382386
scopeProvider.removeVisited(e)
383387
if (found) {
384-
return true
388+
isFound = true
385389
}
386390
}
387391
}
@@ -392,19 +396,19 @@ class KerMLScope extends AbstractScope implements ISysMLScope {
392396
for (type : implicitTypes) {
393397
val found = type.resolveIfUnvisited(qn, false, visited, newRedefined, isInheriting, false, true, false)
394398
if (found) {
395-
return true
399+
isFound = true
396400
}
397401
}
398402
}
399403
if (ns instanceof Feature) {
400404
val chainingFeature = FeatureUtil.getLastChainingFeatureOf(ns)
401405
if (chainingFeature !== null &&
402406
chainingFeature.resolveIfUnvisited(qn, false, visited, newRedefined, isInheriting, false, true, false)) {
403-
return true;
407+
isFound = true;
404408
}
405409
}
406410
}
407-
return false
411+
return isFound
408412
}
409413

410414
protected def boolean imp(Namespace ns, QualifiedName qn, Set<Namespace> visited, boolean isInsideScope, boolean includeImplicitGen, boolean includeAll) {

0 commit comments

Comments
 (0)