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