Skip to content

Commit e0ac5a2

Browse files
authored
Merge pull request Systems-Modeling#686 from Systems-Modeling/ST6RI-728
ST6RI-728 Name resolution of multiply inherited redefined features is not correct
2 parents 55e34e2 + 175dbc5 commit e0ac5a2

5 files changed

Lines changed: 166 additions & 42 deletions

File tree

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,23 @@
11
package Redefinition {
2-
class Occurrence;
3-
class Transfer {
4-
feature transferSource;
5-
feature item;
6-
assoc SourceOutputLink specializes Objects::BinaryLinkObject {
7-
end [1] feature source: Occurrence;
8-
end [1..*] feature target: Occurrence;
9-
}
10-
connector sourceOutputLink: SourceOutputLink[1..*] from transferSource to item {
11-
feature startShot: Occurrence redefines SourceOutputLink::startShot;
12-
feature endShot: Occurrence redefines SourceOutputLink::endShot;
13-
}
2+
3+
classifier A {
4+
feature f;
5+
}
6+
7+
classifier B specializes A {
8+
feature redefines f {
9+
feature g;
10+
}
11+
}
12+
13+
classifier C specializes A, B {
14+
feature subsets f {
15+
feature redefines g;
16+
}
17+
}
18+
19+
class X {
20+
feature redefines startShot;
21+
feature redefines endShot;
1422
}
1523
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
//* XPECT_SETUP org.omg.kerml.xpect.tests.parsing.KerMLParsingTest
2+
ResourceSet {
3+
ThisFile {}
4+
File {from ="/library/Base.kerml"}
5+
File {from ="/library/Links.kerml"}
6+
File {from ="/library/Occurrences.kerml"}
7+
}
8+
Workspace {
9+
JavaProject {
10+
SrcFolder {
11+
ThisFile {}
12+
File {from ="/library/Base.kerml"}
13+
File {from ="/library/Links.kerml"}
14+
File {from ="/library/Occurrences.kerml"}
15+
}
16+
}
17+
}
18+
END_SETUP
19+
*/
20+
21+
// XPECT noErrors ---> ""
22+
package Redefinition {
23+
24+
classifier A {
25+
feature f;
26+
}
27+
28+
classifier B specializes A {
29+
feature redefines f {
30+
feature g;
31+
}
32+
}
33+
34+
classifier C specializes A, B {
35+
feature subsets f {
36+
feature redefines g;
37+
}
38+
}
39+
40+
class X {
41+
feature redefines startShot;
42+
feature redefines endShot;
43+
}
44+
}

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) {

sysml.library/.index.json

Lines changed: 70 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90772,8 +90772,76 @@
9077290772
"~Port"
9077390773
],
9077490774
"Interfaces::Interface::participant::thisParticipant": [
90775+
"differencesOf",
90776+
"dispatchScope",
90777+
"enactedPerformances",
90778+
"endShot",
90779+
"immediatePredecessors",
90780+
"immediateSuccessors",
90781+
"incomingTransferSort",
90782+
"incomingTransfers",
90783+
"incomingTransfersToSelf",
90784+
"innerSpaceDimension",
90785+
"innerSpaceOccurrences",
90786+
"interfacingPorts",
90787+
"intersectionsOf",
90788+
"involvingPerformances",
90789+
"isClosed",
90790+
"isDispatch",
90791+
"isRunToCompletion",
90792+
"justOutsideOfOccurrences",
90793+
"largerSpace",
90794+
"localClock",
90795+
"longerOccurrence",
90796+
"matingOccurrences",
90797+
"middleTimeSlice",
90798+
"outerSpaceDimension",
90799+
"outgoingTransfers",
90800+
"outgoingTransfersFromSelf",
90801+
"outsideOfOccurrences",
90802+
"ownedPerformances",
90803+
"portionOf",
90804+
"portionOfLife",
90805+
"portions",
90806+
"predecessors",
90807+
"runToCompletionScope",
90808+
"sameLifeOccurrences",
9077590809
"self",
90776-
"that"
90810+
"shorterOccurrence",
90811+
"smallerSpace",
90812+
"snapshotOf",
90813+
"snapshots",
90814+
"spaceBoundary",
90815+
"spaceBoundaryOf",
90816+
"spaceEnclosedOccurrences",
90817+
"spaceInterior",
90818+
"spaceInteriorOf",
90819+
"spaceShotOf",
90820+
"spaceShots",
90821+
"spaceSliceOf",
90822+
"spaceSlices",
90823+
"spaceTimeCoincidentOccurrences",
90824+
"spaceTimeEnclosedOccurrences",
90825+
"spaceTimeEnclosedPoints",
90826+
"startShot",
90827+
"structuredSpaceBoundary",
90828+
"subobjects",
90829+
"suboccurrences",
90830+
"subports",
90831+
"successors",
90832+
"superoccurrence",
90833+
"surroundedByOccurrences",
90834+
"that",
90835+
"thatOccurrence",
90836+
"this",
90837+
"thisOccurrence",
90838+
"timeCoincidentOccurrences",
90839+
"timeEnclosedOccurrences",
90840+
"timeSliceOf",
90841+
"timeSlices",
90842+
"unionsOf",
90843+
"withoutOccurrences",
90844+
"~Port"
9077790845
],
9077890846
"Interfaces::binaryInterfaces": [
9077990847
"boundingShapes",
@@ -280122,5 +280190,5 @@
280122280190
"withoutOccurrences"
280123280191
]
280124280192
},
280125-
"checksum": "13b28eb14a5a3cf09e96c180e81b2b10f51730a11d8389122e1345a11525c9c2"
280193+
"checksum": "83ebd85a5305dcef0cc1f3f11c219737ad8f38448d8bc28af253c0a2d8af413e"
280126280194
}

sysml.library/Domain Libraries/Geometry/ShapeItems.sysml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -252,8 +252,8 @@ standard library package ShapeItems {
252252
item :>> edges [1];
253253
}
254254
item :>> edges : Ellipse [1] = shape {
255-
attribute :>> edges::innerSpaceDimension, Ellipse::innerSpaceDimension;
256-
ref item :>> edges::vertices, Ellipse::vertices;
255+
attribute :>> Shell::edges::innerSpaceDimension, Ellipse::innerSpaceDimension;
256+
ref item :>> Shell::edges::vertices, Ellipse::vertices;
257257
}
258258
item :>> vertices [0];
259259
}

0 commit comments

Comments
 (0)