sysmlpy 0.40.0__tar.gz → 0.42.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (148) hide show
  1. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/PKG-INFO +5 -1
  2. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/README.md +4 -0
  3. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/pyproject.toml +1 -1
  4. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/__init__.py +1 -1
  5. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/antlr_visitor.py +248 -159
  6. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/grammar/classes.py +26 -17
  7. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/semantic.py +42 -9
  8. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/usage.py +144 -69
  9. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/LICENSE +0 -0
  10. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/__main__.py +0 -0
  11. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/antlr/README.md +0 -0
  12. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/antlr/SysMLv2Lexer.interp +0 -0
  13. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/antlr/SysMLv2Lexer.py +0 -0
  14. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/antlr/SysMLv2Lexer.tokens +0 -0
  15. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/antlr/SysMLv2Parser.interp +0 -0
  16. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/antlr/SysMLv2Parser.py +0 -0
  17. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/antlr/SysMLv2Parser.tokens +0 -0
  18. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/antlr/SysMLv2ParserListener.py +0 -0
  19. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/antlr/SysMLv2ParserVisitor.py +0 -0
  20. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/antlr/src/sysmlpy/grammar/antlr4/SysMLv2Lexer.interp +0 -0
  21. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/antlr/src/sysmlpy/grammar/antlr4/SysMLv2Lexer.py +0 -0
  22. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/antlr/src/sysmlpy/grammar/antlr4/SysMLv2Lexer.tokens +0 -0
  23. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/antlr_parser.py +0 -0
  24. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/boxes_view.py +0 -0
  25. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/definition.py +0 -0
  26. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/examples/attribute_values.py +0 -0
  27. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/examples/part_attributes.py +0 -0
  28. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/examples/tuples_sequences.py +0 -0
  29. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/formatting.py +0 -0
  30. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/grammar/antlr4/README.md +0 -0
  31. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/grammar/antlr4/SysMLv2Lexer.g4 +0 -0
  32. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/grammar/antlr4/SysMLv2Lexer.interp +0 -0
  33. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/grammar/antlr4/SysMLv2Lexer.py +0 -0
  34. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/grammar/antlr4/SysMLv2Lexer.tokens +0 -0
  35. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/grammar/antlr4/SysMLv2Parser.g4 +0 -0
  36. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/grammar/antlr4/SysMLv2Parser.interp +0 -0
  37. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/grammar/antlr4/SysMLv2Parser.py +0 -0
  38. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/grammar/antlr4/SysMLv2Parser.tokens +0 -0
  39. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/grammar/antlr4/SysMLv2ParserListener.py +0 -0
  40. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/grammar/antlr4/SysMLv2ParserVisitor.py +0 -0
  41. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/grammar/antlr4/desc.xml +0 -0
  42. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/grammar/antlr4/examples/camera.sysml +0 -0
  43. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/grammar/antlr4/examples/toaster-system.sysml +0 -0
  44. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/grammar/antlr4/examples/vehicle-model.sysml +0 -0
  45. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/grammar/antlr4/pom.xml +0 -0
  46. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/library/LICENSE +0 -0
  47. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/library/README.md +0 -0
  48. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/library/__init__.py +0 -0
  49. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/library/domain/Analysis/AnalysisTooling.sysml +0 -0
  50. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/library/domain/Analysis/SampledFunctions.sysml +0 -0
  51. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/library/domain/Analysis/StateSpaceRepresentation.sysml +0 -0
  52. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/library/domain/Analysis/TradeStudies.sysml +0 -0
  53. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/library/domain/Cause and Effect/CausationConnections.sysml +0 -0
  54. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/library/domain/Cause and Effect/CauseAndEffect.sysml +0 -0
  55. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/library/domain/Geometry/ShapeItems.sysml +0 -0
  56. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/library/domain/Geometry/SpatialItems.sysml +0 -0
  57. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/library/domain/Metadata/ImageMetadata.sysml +0 -0
  58. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/library/domain/Metadata/ModelingMetadata.sysml +0 -0
  59. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/library/domain/Metadata/ParametersOfInterestMetadata.sysml +0 -0
  60. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/library/domain/Metadata/RiskMetadata.sysml +0 -0
  61. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/library/domain/Quantities and Units/ISQ.sysml +0 -0
  62. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/library/domain/Quantities and Units/ISQAcoustics.sysml +0 -0
  63. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/library/domain/Quantities and Units/ISQAtomicNuclear.sysml +0 -0
  64. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/library/domain/Quantities and Units/ISQBase.sysml +0 -0
  65. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/library/domain/Quantities and Units/ISQCharacteristicNumbers.sysml +0 -0
  66. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/library/domain/Quantities and Units/ISQChemistryMolecular.sysml +0 -0
  67. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/library/domain/Quantities and Units/ISQCondensedMatter.sysml +0 -0
  68. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/library/domain/Quantities and Units/ISQElectromagnetism.sysml +0 -0
  69. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/library/domain/Quantities and Units/ISQInformation.sysml +0 -0
  70. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/library/domain/Quantities and Units/ISQLight.sysml +0 -0
  71. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/library/domain/Quantities and Units/ISQMechanics.sysml +0 -0
  72. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/library/domain/Quantities and Units/ISQSpaceTime.sysml +0 -0
  73. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/library/domain/Quantities and Units/ISQThermodynamics.sysml +0 -0
  74. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/library/domain/Quantities and Units/MeasurementRefCalculations.sysml +0 -0
  75. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/library/domain/Quantities and Units/MeasurementReferences.sysml +0 -0
  76. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/library/domain/Quantities and Units/Quantities.sysml +0 -0
  77. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/library/domain/Quantities and Units/QuantityCalculations.sysml +0 -0
  78. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/library/domain/Quantities and Units/SI.sysml +0 -0
  79. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/library/domain/Quantities and Units/SIPrefixes.sysml +0 -0
  80. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/library/domain/Quantities and Units/TensorCalculations.sysml +0 -0
  81. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/library/domain/Quantities and Units/Time.sysml +0 -0
  82. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/library/domain/Quantities and Units/USCustomaryUnits.sysml +0 -0
  83. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/library/domain/Quantities and Units/VectorCalculations.sysml +0 -0
  84. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/library/domain/Requirement Derivation/DerivationConnections.sysml +0 -0
  85. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/library/domain/Requirement Derivation/RequirementDerivation.sysml +0 -0
  86. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/library/kernel/Base.kerml +0 -0
  87. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/library/kernel/BaseFunctions.kerml +0 -0
  88. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/library/kernel/BooleanFunctions.kerml +0 -0
  89. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/library/kernel/Clocks.kerml +0 -0
  90. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/library/kernel/CollectionFunctions.kerml +0 -0
  91. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/library/kernel/Collections.kerml +0 -0
  92. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/library/kernel/ComplexFunctions.kerml +0 -0
  93. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/library/kernel/ControlFunctions.kerml +0 -0
  94. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/library/kernel/ControlPerformances.kerml +0 -0
  95. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/library/kernel/DataFunctions.kerml +0 -0
  96. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/library/kernel/FeatureReferencingPerformances.kerml +0 -0
  97. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/library/kernel/IntegerFunctions.kerml +0 -0
  98. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/library/kernel/KerML.kerml +0 -0
  99. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/library/kernel/Links.kerml +0 -0
  100. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/library/kernel/Metaobjects.kerml +0 -0
  101. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/library/kernel/NaturalFunctions.kerml +0 -0
  102. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/library/kernel/NumericalFunctions.kerml +0 -0
  103. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/library/kernel/Objects.kerml +0 -0
  104. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/library/kernel/Observation.kerml +0 -0
  105. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/library/kernel/OccurrenceFunctions.kerml +0 -0
  106. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/library/kernel/Occurrences.kerml +0 -0
  107. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/library/kernel/Performances.kerml +0 -0
  108. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/library/kernel/RationalFunctions.kerml +0 -0
  109. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/library/kernel/RealFunctions.kerml +0 -0
  110. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/library/kernel/ScalarFunctions.kerml +0 -0
  111. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/library/kernel/ScalarValues.kerml +0 -0
  112. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/library/kernel/SequenceFunctions.kerml +0 -0
  113. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/library/kernel/SpatialFrames.kerml +0 -0
  114. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/library/kernel/StatePerformances.kerml +0 -0
  115. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/library/kernel/StringFunctions.kerml +0 -0
  116. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/library/kernel/Transfers.kerml +0 -0
  117. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/library/kernel/TransitionPerformances.kerml +0 -0
  118. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/library/kernel/TrigFunctions.kerml +0 -0
  119. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/library/kernel/Triggers.kerml +0 -0
  120. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/library/kernel/VectorFunctions.kerml +0 -0
  121. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/library/kernel/VectorValues.kerml +0 -0
  122. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/library/systems/Actions.sysml +0 -0
  123. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/library/systems/Allocations.sysml +0 -0
  124. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/library/systems/AnalysisCases.sysml +0 -0
  125. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/library/systems/Attributes.sysml +0 -0
  126. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/library/systems/Calculations.sysml +0 -0
  127. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/library/systems/Cases.sysml +0 -0
  128. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/library/systems/Connections.sysml +0 -0
  129. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/library/systems/Constraints.sysml +0 -0
  130. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/library/systems/Flows.sysml +0 -0
  131. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/library/systems/Interfaces.sysml +0 -0
  132. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/library/systems/Items.sysml +0 -0
  133. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/library/systems/Metadata.sysml +0 -0
  134. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/library/systems/Parts.sysml +0 -0
  135. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/library/systems/Ports.sysml +0 -0
  136. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/library/systems/Requirements.sysml +0 -0
  137. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/library/systems/StandardViewDefinitions.sysml +0 -0
  138. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/library/systems/States.sysml +0 -0
  139. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/library/systems/SysML.sysml +0 -0
  140. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/library/systems/UseCases.sysml +0 -0
  141. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/library/systems/VerificationCases.sysml +0 -0
  142. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/library/systems/Views.sysml +0 -0
  143. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/navigate.py +0 -0
  144. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/plantuml.py +0 -0
  145. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/project.py +0 -0
  146. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/store.py +0 -0
  147. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/us_customary_units.txt +0 -0
  148. {sysmlpy-0.40.0 → sysmlpy-0.42.0}/src/sysmlpy/validator.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sysmlpy
3
- Version: 0.40.0
3
+ Version: 0.42.0
4
4
  Summary:
5
5
  License-File: LICENSE
6
6
  Author: Jon R. Fox (mycr0ft)
@@ -39,6 +39,10 @@ The project had diverged so much from sysml2py that a new name, sysmlpy, was sel
39
39
 
40
40
  ![Lines of Code Over Time](loc_history.svg)
41
41
 
42
+ **v0.42.0:** Two deep fixes in the specialization layer. (1) `satisfy R : T by p;` and `assert someConstraint : CType;` crashed with `NameError` — the makers called a helper that was never defined; all three sites now use `_build_full_specialization_from_fsp`. (2) Chained re-declarations (`attribute :> base.x;`) dropped every segment after the first, at both visitor and grammar layers — new visitor helpers emit one Owned* dict per source chain (head + `OwnedFeatureChain`), grammar classes keep both parts, `redefined_name` resolves to the leaf segment, and the semantic analyzer now reports/resolves full dotted names (`Undefined symbol 'missing.chain'`). 14 tests in `tests/redefined_name_test.py`.
43
+
44
+ **v0.41.0:** Full-specialization capture across all usage kinds — v0.40.0 fixed `attributeUsage` only; actions, calculations, constraints, requirements, use cases, interfaces and nested occurrences still dropped `:>`, `:>>`, `::>` specializations. New `_full_specialization_for_ctx` helper walks any usage-like context to its featureSpecializationPart; twelve visitor sites now use it (typed-by kept as fallback). `Action.load_from_grammar` captures all four kinds and the hand-rolled dumps on Action/Interface/UseCase/Requirement render them (`action a2 ::> RefType;`). `Usage.redefined_name` now works on deeper declaration nestings too. 10 tests in `tests/redefined_name_test.py`.
45
+
42
46
  **v0.40.0:** `References` (`::>` / `references` keyword) implemented end-to-end — previously the grammar-side `FeatureSpecialization` had a silent "not yet implemented" stub and the visitor never emitted dicts for it, so `ref attribute ::> X;` lost its specialization on round-trip (dump emitted `attribute ;`). New `References` grammar class mirrors `Redefinitions`; visitor branches in both full-specialization builders now cover the operator and keyword forms. The top-level `attributeUsage` path was the only one still using the typed-by-only helper; it now uses `_build_full_specialization_from_ctx` so all four kinds (Typings, Subsettings, Redefinitions, References) round-trip. `redefined_name` / `display_name` already handled this case. New `test_attribute_ref_references_operator_roundtrip` in `tests/grammar_test.py`; two new cases in `tests/redefined_name_test.py`. 97/97 grammar round-trip tests pass.
43
47
 
44
48
  **v0.39.0:** Redefined-Usage name resolution — `attribute :>> exampleAttribute = ...;` previously dumped the name correctly but exposed a UUID sentinel via `attribute.name`. Two new helpers surface the user-visible identifier without changing the historical `self.name` semantics: `Usage.redefined_name` (last identifier segment of the first re-declaration chain — `Redefinitions` / `Subsettings` / `References`) and `Usage.display_name` (UUID-aware user-meaningful name). `get_value()`, `dump()`, and `get_child()` continue to work unchanged. New `tests/redefined_name_test.py` (6 tests) — the original two-package `DummyDefinitionModel` / `DummyUsageModel` round-trips and the helper properties are exercised.
@@ -14,6 +14,10 @@ The project had diverged so much from sysml2py that a new name, sysmlpy, was sel
14
14
 
15
15
  ![Lines of Code Over Time](loc_history.svg)
16
16
 
17
+ **v0.42.0:** Two deep fixes in the specialization layer. (1) `satisfy R : T by p;` and `assert someConstraint : CType;` crashed with `NameError` — the makers called a helper that was never defined; all three sites now use `_build_full_specialization_from_fsp`. (2) Chained re-declarations (`attribute :> base.x;`) dropped every segment after the first, at both visitor and grammar layers — new visitor helpers emit one Owned* dict per source chain (head + `OwnedFeatureChain`), grammar classes keep both parts, `redefined_name` resolves to the leaf segment, and the semantic analyzer now reports/resolves full dotted names (`Undefined symbol 'missing.chain'`). 14 tests in `tests/redefined_name_test.py`.
18
+
19
+ **v0.41.0:** Full-specialization capture across all usage kinds — v0.40.0 fixed `attributeUsage` only; actions, calculations, constraints, requirements, use cases, interfaces and nested occurrences still dropped `:>`, `:>>`, `::>` specializations. New `_full_specialization_for_ctx` helper walks any usage-like context to its featureSpecializationPart; twelve visitor sites now use it (typed-by kept as fallback). `Action.load_from_grammar` captures all four kinds and the hand-rolled dumps on Action/Interface/UseCase/Requirement render them (`action a2 ::> RefType;`). `Usage.redefined_name` now works on deeper declaration nestings too. 10 tests in `tests/redefined_name_test.py`.
20
+
17
21
  **v0.40.0:** `References` (`::>` / `references` keyword) implemented end-to-end — previously the grammar-side `FeatureSpecialization` had a silent "not yet implemented" stub and the visitor never emitted dicts for it, so `ref attribute ::> X;` lost its specialization on round-trip (dump emitted `attribute ;`). New `References` grammar class mirrors `Redefinitions`; visitor branches in both full-specialization builders now cover the operator and keyword forms. The top-level `attributeUsage` path was the only one still using the typed-by-only helper; it now uses `_build_full_specialization_from_ctx` so all four kinds (Typings, Subsettings, Redefinitions, References) round-trip. `redefined_name` / `display_name` already handled this case. New `test_attribute_ref_references_operator_roundtrip` in `tests/grammar_test.py`; two new cases in `tests/redefined_name_test.py`. 97/97 grammar round-trip tests pass.
18
22
 
19
23
  **v0.39.0:** Redefined-Usage name resolution — `attribute :>> exampleAttribute = ...;` previously dumped the name correctly but exposed a UUID sentinel via `attribute.name`. Two new helpers surface the user-visible identifier without changing the historical `self.name` semantics: `Usage.redefined_name` (last identifier segment of the first re-declaration chain — `Redefinitions` / `Subsettings` / `References`) and `Usage.display_name` (UUID-aware user-meaningful name). `get_value()`, `dump()`, and `get_child()` continue to work unchanged. New `tests/redefined_name_test.py` (6 tests) — the original two-package `DummyDefinitionModel` / `DummyUsageModel` round-trips and the helper properties are exercised.
@@ -6,7 +6,7 @@ build-backend = "poetry.core.masonry.api"
6
6
 
7
7
  [project]
8
8
  name = "sysmlpy"
9
- version = "0.40.0"
9
+ version = "0.42.0"
10
10
  description = ""
11
11
  authors = [{ name = "Jon R. Fox (mycr0ft)", email = "jon.fox@drfox.com" }]
12
12
  readme = "README.md"
@@ -25,7 +25,7 @@ __all__ = [
25
25
  "render_state_transition_view_svg", "boxes_view",
26
26
  ]
27
27
  __author__ = "Jon Fox"
28
- __version__ = "0.40.0"
28
+ __version__ = "0.42.0"
29
29
 
30
30
  from sysmlpy.usage import (
31
31
  Item, Attribute, Part, Port, Action, Reference, UseCase, Requirement, Interface, Message,
@@ -1432,7 +1432,11 @@ def _make_use_case_usage_dict(ctx, prefix=None):
1432
1432
  if typed_by is None:
1433
1433
  typed_by = _get_action_usage_subsetted_by(ctx)
1434
1434
 
1435
- specialization = _build_specialization(typed_by) if typed_by else None
1435
+ spec_full = _full_specialization_for_ctx(ctx)
1436
+ if spec_full is not None:
1437
+ specialization = spec_full
1438
+ else:
1439
+ specialization = _build_specialization(typed_by) if typed_by else None
1436
1440
  occ_prefix = _get_occurrence_usage_prefix(ctx) if ctx else None
1437
1441
 
1438
1442
  # Get case body items
@@ -2208,7 +2212,7 @@ def _make_assert_constraint_usage_dict(acu_ctx, prefix=None):
2208
2212
 
2209
2213
  if hasattr(acu_ctx, 'featureSpecializationPart') and acu_ctx.featureSpecializationPart():
2210
2214
  fsp_ctx = acu_ctx.featureSpecializationPart()
2211
- fsp = _build_feature_specialization_part(fsp_ctx)
2215
+ fsp = _build_full_specialization_from_fsp(fsp_ctx)
2212
2216
 
2213
2217
  declaration = None
2214
2218
  if hasattr(acu_ctx, 'constraintUsageDeclaration') and acu_ctx.constraintUsageDeclaration():
@@ -2311,7 +2315,7 @@ def _make_satisfy_requirement_usage_dict(sru_ctx, prefix=None):
2311
2315
 
2312
2316
  if hasattr(sru_ctx, 'featureSpecializationPart') and sru_ctx.featureSpecializationPart():
2313
2317
  fsp_ctx = sru_ctx.featureSpecializationPart()
2314
- fsp = _build_feature_specialization_part(fsp_ctx)
2318
+ fsp = _build_full_specialization_from_fsp(fsp_ctx)
2315
2319
  elif hasattr(sru_ctx, 'REQUIREMENT') and sru_ctx.REQUIREMENT():
2316
2320
  if hasattr(sru_ctx, 'usageDeclaration') and sru_ctx.usageDeclaration():
2317
2321
  ud = sru_ctx.usageDeclaration()
@@ -3000,8 +3004,13 @@ def _make_action_usage_element(ctx, member_prefix=None):
3000
3004
  # Get body items
3001
3005
  action_items = _visit_action_body_items(ctx)
3002
3006
 
3003
- # Build specialization if typed_by is present
3004
- specialization = _build_specialization(typed_by) if typed_by else None
3007
+ # Full specialization (Typings + Subsettings + Redefinitions +
3008
+ # References); typed-by fallback for odd contexts.
3009
+ spec_full = _full_specialization_for_ctx(ctx)
3010
+ if spec_full is not None:
3011
+ specialization = spec_full
3012
+ else:
3013
+ specialization = _build_specialization(typed_by) if typed_by else None
3005
3014
 
3006
3015
  return {
3007
3016
  "name": "BehaviorUsageMember",
@@ -6143,7 +6152,11 @@ def _make_calculation_usage_dict(ctx, prefix=None):
6143
6152
  if typed_by is None:
6144
6153
  typed_by = _get_action_usage_subsetted_by(ctx)
6145
6154
 
6146
- specialization = _build_specialization(typed_by) if typed_by else None
6155
+ spec_full = _full_specialization_for_ctx(ctx)
6156
+ if spec_full is not None:
6157
+ specialization = spec_full
6158
+ else:
6159
+ specialization = _build_specialization(typed_by) if typed_by else None
6147
6160
  body_parts = _visit_calculation_body_items(ctx)
6148
6161
  occ_prefix = _get_occurrence_usage_prefix(ctx) if ctx else None
6149
6162
 
@@ -6253,7 +6266,11 @@ def _make_constraint_usage_dict(ctx, prefix=None):
6253
6266
  if typed_by is None:
6254
6267
  typed_by = _get_action_usage_subsetted_by(ctx)
6255
6268
 
6256
- specialization = _build_specialization(typed_by) if typed_by else None
6269
+ spec_full = _full_specialization_for_ctx(ctx)
6270
+ if spec_full is not None:
6271
+ specialization = spec_full
6272
+ else:
6273
+ specialization = _build_specialization(typed_by) if typed_by else None
6257
6274
  body_parts = _visit_calculation_body_items(ctx)
6258
6275
  occ_prefix = _get_occurrence_usage_prefix(ctx) if ctx else None
6259
6276
 
@@ -6336,7 +6353,11 @@ def _make_requirement_usage_dict(ctx, prefix=None):
6336
6353
  if typed_by is None:
6337
6354
  typed_by = _get_action_usage_subsetted_by(ctx)
6338
6355
 
6339
- specialization = _build_specialization(typed_by) if typed_by else None
6356
+ spec_full = _full_specialization_for_ctx(ctx)
6357
+ if spec_full is not None:
6358
+ specialization = spec_full
6359
+ else:
6360
+ specialization = _build_specialization(typed_by) if typed_by else None
6340
6361
  occ_prefix = _get_occurrence_usage_prefix(ctx) if ctx else None
6341
6362
 
6342
6363
  # Get requirement body items
@@ -6505,7 +6526,11 @@ def _make_interface_usage_dict(ctx, prefix=None):
6505
6526
  if item_dict:
6506
6527
  body_items.append(item_dict)
6507
6528
 
6508
- specialization = _build_specialization(typed_by) if typed_by else None
6529
+ spec_full = _full_specialization_for_ctx(ctx)
6530
+ if spec_full is not None:
6531
+ specialization = spec_full
6532
+ else:
6533
+ specialization = _build_specialization(typed_by) if typed_by else None
6509
6534
 
6510
6535
  interface_end_members = []
6511
6536
  if interface_part:
@@ -9086,7 +9111,7 @@ def _visit_requirement_constraint_usage(rcu_ctx):
9086
9111
  fs = []
9087
9112
  if hasattr(rcu_ctx, 'featureSpecializationPart') and rcu_ctx.featureSpecializationPart():
9088
9113
  fsp_ctx = rcu_ctx.featureSpecializationPart()
9089
- fsp = _build_feature_specialization_part(fsp_ctx)
9114
+ fsp = _build_full_specialization_from_fsp(fsp_ctx)
9090
9115
  if fsp and "specialization" in fsp:
9091
9116
  fs = fsp["specialization"]
9092
9117
 
@@ -9705,7 +9730,11 @@ def _visit_nested_occurrence_usage(occ_elem):
9705
9730
  typed_by = _get_action_usage_typed_by(ctx)
9706
9731
  if typed_by is None:
9707
9732
  typed_by = _get_action_usage_subsetted_by(ctx)
9708
- specialization = _build_specialization(typed_by) if typed_by else None
9733
+ spec_full = _full_specialization_for_ctx(ctx)
9734
+ if spec_full is not None:
9735
+ specialization = spec_full
9736
+ else:
9737
+ specialization = _build_specialization(typed_by) if typed_by else None
9709
9738
 
9710
9739
  occ_prefix = _get_occurrence_usage_prefix(ctx)
9711
9740
 
@@ -11225,8 +11254,13 @@ def _visit_usage_element_dict(usage_elem_ctx, prefix=None):
11225
11254
  # Get body items
11226
11255
  action_items = _visit_action_body_items(ctx)
11227
11256
 
11228
- # Build specialization if typed_by is present
11229
- specialization = _build_specialization(typed_by) if typed_by else None
11257
+ # Full specialization (Typings + Subsettings + Redefinitions +
11258
+ # References); typed-by fallback for odd contexts.
11259
+ spec_full = _full_specialization_for_ctx(ctx)
11260
+ if spec_full is not None:
11261
+ specialization = spec_full
11262
+ else:
11263
+ specialization = _build_specialization(typed_by) if typed_by else None
11230
11264
 
11231
11265
  return {
11232
11266
  "name": "PackageMember",
@@ -11527,6 +11561,137 @@ def _get_action_usage_subsetted_by(ctx):
11527
11561
  return None
11528
11562
 
11529
11563
 
11564
+ def _dotted_segments(owned_ctx):
11565
+ """Segments of an ownedSubsetting / ownedRedefinition /
11566
+ ownedReferenceSubsetting context.
11567
+
11568
+ Grammar: qualifiedName (DOT qualifiedName)* — e.g. ``base.x`` yields
11569
+ ``['base', 'x']``. Each segment may itself be '::'-qualified.
11570
+ """
11571
+ segs = []
11572
+ if owned_ctx is None:
11573
+ return segs
11574
+ for c2 in owned_ctx.children:
11575
+ if type(c2).__name__ == 'QualifiedNameContext':
11576
+ segs.append(c2.getText())
11577
+ return segs
11578
+
11579
+
11580
+ def _emit_owned_chain(dict_name, feature_key, segs):
11581
+ """Build an Owned{Subsetting,Redefinition,ReferenceSubsetting} dict
11582
+ from dotted segments: first segment becomes the direct feature, the
11583
+ remainder become an OwnedFeatureChain so chained forms like
11584
+ ``:> base.x`` survive round-trip."""
11585
+ head = {
11586
+ "name": "QualifiedName",
11587
+ "names": segs[0].split("::"),
11588
+ }
11589
+ owned_related = []
11590
+ if len(segs) > 1:
11591
+ chain_elements = [
11592
+ {
11593
+ "name": "OwnedFeatureChaining",
11594
+ "chainingFeature": {"name": "QualifiedName", "names": s.split("::")},
11595
+ }
11596
+ for s in segs[1:]
11597
+ ]
11598
+ owned_related.append({
11599
+ "name": "OwnedFeatureChain",
11600
+ "feature": {
11601
+ "name": "FeatureChain",
11602
+ "ownedRelationship": chain_elements,
11603
+ },
11604
+ })
11605
+ return {
11606
+ "name": dict_name,
11607
+ feature_key: head,
11608
+ "ownedRelatedElement": owned_related,
11609
+ }
11610
+
11611
+
11612
+ def _collect_owned_contexts(wrapper_children, direct_type, wrapper_types):
11613
+ """Yield each Owned*Context found under a Subsettings/Redefinitions/
11614
+ References rule context. Handles both direct children and one of the
11615
+ keyword-wrapper contexts (SubsetsContext, RedefinesContext, …)."""
11616
+ for child in wrapper_children:
11617
+ child_name = type(child).__name__
11618
+ if child_name == direct_type:
11619
+ yield child
11620
+ elif child_name in wrapper_types:
11621
+ for c3 in child.children:
11622
+ if type(c3).__name__ == direct_type:
11623
+ yield c3
11624
+
11625
+
11626
+ def _full_specialization_for_ctx(ctx):
11627
+ """Best-effort full specialization for any usage-like context.
11628
+
11629
+ Tries, in order:
11630
+ 1. ctx.usage().usageDeclaration().featureSpecializationPart()
11631
+ (whole-usage contexts: attributeUsage, partUsage, …)
11632
+ 2. ctx.usageDeclaration().featureSpecializationPart()
11633
+ 3. ctx.<x>UsageDeclaration().usageDeclaration().featureSpecializationPart()
11634
+ for any ``*UsageDeclaration`` accessor on ctx
11635
+ (actionUsageDeclaration, constraintUsageDeclaration, …)
11636
+
11637
+ Returns None when no path yields a featureSpecializationPart. Callers
11638
+ that previously did ``_build_specialization(typed_by)`` can call this
11639
+ instead to also capture Redefinitions / Subsettings / References.
11640
+ """
11641
+ if ctx is None:
11642
+ return None
11643
+
11644
+ def _fsp_from_ud(ud):
11645
+ if ud is None:
11646
+ return None
11647
+ if isinstance(ud, list):
11648
+ ud = ud[0] if ud else None
11649
+ if ud is None:
11650
+ return None
11651
+ fsp_getter = getattr(ud, "featureSpecializationPart", None)
11652
+ if callable(fsp_getter) and fsp_getter():
11653
+ return _build_full_specialization_from_fsp(fsp_getter())
11654
+ return None
11655
+
11656
+ # 1) whole-usage context
11657
+ usage = getattr(ctx, "usage", None)
11658
+ if callable(usage):
11659
+ u = usage()
11660
+ if u is not None and hasattr(u, "usageDeclaration"):
11661
+ spec = _fsp_from_ud(u.usageDeclaration())
11662
+ if spec is not None:
11663
+ return spec
11664
+
11665
+ # 2) direct usageDeclaration on ctx
11666
+ ud_getter = getattr(ctx, "usageDeclaration", None)
11667
+ if callable(ud_getter):
11668
+ spec = _fsp_from_ud(ud_getter())
11669
+ if spec is not None:
11670
+ return spec
11671
+
11672
+ # 3) any *UsageDeclaration holder (actionUsageDeclaration, …)
11673
+ for attr in sorted(dir(ctx)):
11674
+ if not attr.endswith("UsageDeclaration") or attr == "usageDeclaration":
11675
+ continue
11676
+ getter = getattr(ctx, attr, None)
11677
+ if callable(getter):
11678
+ try:
11679
+ holder = getter()
11680
+ except Exception:
11681
+ continue
11682
+ if holder is None:
11683
+ continue
11684
+ if callable(getattr(holder, "usageDeclaration", None)):
11685
+ spec = _fsp_from_ud(holder.usageDeclaration())
11686
+ if spec is not None:
11687
+ return spec
11688
+ spec = _fsp_from_ud(holder)
11689
+ if spec is not None:
11690
+ return spec
11691
+
11692
+ return None
11693
+
11694
+
11530
11695
  def _build_specialization(typed_by):
11531
11696
  """Build the specialization dictionary structure for a typed-by reference."""
11532
11697
  if not typed_by:
@@ -11745,30 +11910,19 @@ def _build_full_specialization_from_ctx(ctx):
11745
11910
  # redef_ctx can be a single RedefinitionsContext or a list
11746
11911
  if not isinstance(redef_ctx, list):
11747
11912
  redef_ctx = [redef_ctx]
11748
- redef_names = []
11913
+ owned = []
11749
11914
  for rc in redef_ctx:
11750
- # RedefinitionsContext → [RedefinesContext, ...] → [OwnedRedefinitionContext, ...] → QualifiedNameContext
11751
- for child in rc.children:
11752
- child_name = type(child).__name__
11753
- if child_name == 'OwnedRedefinitionContext':
11754
- for c2 in child.children:
11755
- if type(c2).__name__ == 'QualifiedNameContext':
11756
- redef_names.append(c2.getText())
11757
- elif child_name == 'RedefinesContext':
11758
- for c2 in child.children:
11759
- if type(c2).__name__ == 'OwnedRedefinitionContext':
11760
- for c3 in c2.children:
11761
- if type(c3).__name__ == 'QualifiedNameContext':
11762
- redef_names.append(c3.getText())
11763
- if redef_names:
11764
- owned = [
11765
- {
11766
- "name": "OwnedRedefinition",
11767
- "redefinedFeature": {"name": "QualifiedName", "names": n.split("::")},
11768
- "ownedRelatedElement": []
11769
- }
11770
- for n in redef_names
11771
- ]
11915
+ # OwnedRedefinitionContext may be a dotted chain
11916
+ # (qualifiedName (DOT qualifiedName)*).
11917
+ for or_ctx in _collect_owned_contexts(
11918
+ rc.children, 'OwnedRedefinitionContext',
11919
+ ('RedefinesContext',),
11920
+ ):
11921
+ segs = _dotted_segments(or_ctx)
11922
+ if segs:
11923
+ owned.append(_emit_owned_chain(
11924
+ 'OwnedRedefinition', 'redefinedFeature', segs))
11925
+ if owned:
11772
11926
  specialization_list.append({
11773
11927
  "name": "FeatureSpecialization",
11774
11928
  "ownedRelationship": {
@@ -11783,36 +11937,19 @@ def _build_full_specialization_from_ctx(ctx):
11783
11937
  # sub_ctx can be a single SubsettingsContext or a list
11784
11938
  if not isinstance(sub_ctx, list):
11785
11939
  sub_ctx = [sub_ctx]
11786
- sub_names = []
11940
+ owned = []
11787
11941
  for sc in sub_ctx:
11788
- # SubsettingsContext → [SubsetsContext, ...] → [OwnedSubsettingContext] → QualifiedNameContext
11789
- for child in sc.children:
11790
- child_name = type(child).__name__
11791
- if child_name == 'OwnedSubsettingContext':
11792
- for c2 in child.children:
11793
- if type(c2).__name__ == 'QualifiedNameContext':
11794
- sub_names.append(c2.getText())
11795
- elif child_name == 'SubsetsContext':
11796
- for c2 in child.children:
11797
- if type(c2).__name__ == 'OwnedSubsettingContext':
11798
- for c3 in c2.children:
11799
- if type(c3).__name__ == 'QualifiedNameContext':
11800
- sub_names.append(c3.getText())
11801
- elif child_name == 'SpecializesContext':
11802
- for c2 in child.children:
11803
- if type(c2).__name__ == 'OwnedSubsettingContext':
11804
- for c3 in c2.children:
11805
- if type(c3).__name__ == 'QualifiedNameContext':
11806
- sub_names.append(c3.getText())
11807
- if sub_names:
11808
- owned = [
11809
- {
11810
- "name": "OwnedSubsetting",
11811
- "subsettedFeature": {"name": "QualifiedName", "names": n.split("::")},
11812
- "ownedRelatedElement": []
11813
- }
11814
- for n in sub_names
11815
- ]
11942
+ # Each Owned*Context may be a dotted chain
11943
+ # (qualifiedName (DOT qualifiedName)*).
11944
+ for os_ctx in _collect_owned_contexts(
11945
+ sc.children, 'OwnedSubsettingContext',
11946
+ ('SubsetsContext', 'SpecializesContext'),
11947
+ ):
11948
+ segs = _dotted_segments(os_ctx)
11949
+ if segs:
11950
+ owned.append(_emit_owned_chain(
11951
+ 'OwnedSubsetting', 'subsettedFeature', segs))
11952
+ if owned:
11816
11953
  specialization_list.append({
11817
11954
  "name": "FeatureSpecialization",
11818
11955
  "ownedRelationship": {
@@ -11826,29 +11963,18 @@ def _build_full_specialization_from_ctx(ctx):
11826
11963
  ref_ctx = spec.references()
11827
11964
  if not isinstance(ref_ctx, list):
11828
11965
  ref_ctx = [ref_ctx]
11829
- ref_names = []
11966
+ owned = []
11830
11967
  for rc in ref_ctx:
11831
- for child in rc.children:
11832
- child_name = type(child).__name__
11833
- if child_name == 'OwnedReferenceSubsettingContext':
11834
- for c2 in child.children:
11835
- if type(c2).__name__ == 'QualifiedNameContext':
11836
- ref_names.append(c2.getText())
11837
- elif child_name == 'ReferencesContext':
11838
- for c2 in child.children:
11839
- if type(c2).__name__ == 'OwnedReferenceSubsettingContext':
11840
- for c3 in c2.children:
11841
- if type(c3).__name__ == 'QualifiedNameContext':
11842
- ref_names.append(c3.getText())
11843
- if ref_names:
11844
- owned = [
11845
- {
11846
- "name": "OwnedReferenceSubsetting",
11847
- "referencedFeature": {"name": "QualifiedName", "names": n.split("::")},
11848
- "ownedRelatedElement": []
11849
- }
11850
- for n in ref_names
11851
- ]
11968
+ # OwnedReferenceSubsettingContext may be a dotted chain.
11969
+ for ors_ctx in _collect_owned_contexts(
11970
+ rc.children, 'OwnedReferenceSubsettingContext',
11971
+ ('ReferencesContext',),
11972
+ ):
11973
+ segs = _dotted_segments(ors_ctx)
11974
+ if segs:
11975
+ owned.append(_emit_owned_chain(
11976
+ 'OwnedReferenceSubsetting', 'referencedFeature', segs))
11977
+ if owned:
11852
11978
  specialization_list.append({
11853
11979
  "name": "FeatureSpecialization",
11854
11980
  "ownedRelationship": {
@@ -12139,29 +12265,19 @@ def _build_full_specialization_from_fsp(fsp):
12139
12265
  redef_ctx = spec.redefinitions()
12140
12266
  if not isinstance(redef_ctx, list):
12141
12267
  redef_ctx = [redef_ctx]
12142
- redef_names = []
12268
+ owned = []
12143
12269
  for rc in redef_ctx:
12144
- for child in rc.children:
12145
- child_name = type(child).__name__
12146
- if child_name == 'OwnedRedefinitionContext':
12147
- for c2 in child.children:
12148
- if type(c2).__name__ == 'QualifiedNameContext':
12149
- redef_names.append(c2.getText())
12150
- elif child_name == 'RedefinesContext':
12151
- for c2 in child.children:
12152
- if type(c2).__name__ == 'OwnedRedefinitionContext':
12153
- for c3 in c2.children:
12154
- if type(c3).__name__ == 'QualifiedNameContext':
12155
- redef_names.append(c3.getText())
12156
- if redef_names:
12157
- owned = [
12158
- {
12159
- "name": "OwnedRedefinition",
12160
- "redefinedFeature": {"name": "QualifiedName", "names": n.split("::")},
12161
- "ownedRelatedElement": []
12162
- }
12163
- for n in redef_names
12164
- ]
12270
+ # OwnedRedefinitionContext may be a dotted chain
12271
+ # (qualifiedName (DOT qualifiedName)*).
12272
+ for or_ctx in _collect_owned_contexts(
12273
+ rc.children, 'OwnedRedefinitionContext',
12274
+ ('RedefinesContext',),
12275
+ ):
12276
+ segs = _dotted_segments(or_ctx)
12277
+ if segs:
12278
+ owned.append(_emit_owned_chain(
12279
+ 'OwnedRedefinition', 'redefinedFeature', segs))
12280
+ if owned:
12165
12281
  specialization_list.append({
12166
12282
  "name": "FeatureSpecialization",
12167
12283
  "ownedRelationship": {
@@ -12175,35 +12291,19 @@ def _build_full_specialization_from_fsp(fsp):
12175
12291
  sub_ctx = spec.subsettings()
12176
12292
  if not isinstance(sub_ctx, list):
12177
12293
  sub_ctx = [sub_ctx]
12178
- sub_names = []
12294
+ owned = []
12179
12295
  for sc in sub_ctx:
12180
- for child in sc.children:
12181
- child_name = type(child).__name__
12182
- if child_name == 'OwnedSubsettingContext':
12183
- for c2 in child.children:
12184
- if type(c2).__name__ == 'QualifiedNameContext':
12185
- sub_names.append(c2.getText())
12186
- elif child_name == 'SubsetsContext':
12187
- for c2 in child.children:
12188
- if type(c2).__name__ == 'OwnedSubsettingContext':
12189
- for c3 in c2.children:
12190
- if type(c3).__name__ == 'QualifiedNameContext':
12191
- sub_names.append(c3.getText())
12192
- elif child_name == 'SpecializesContext':
12193
- for c2 in child.children:
12194
- if type(c2).__name__ == 'OwnedSubsettingContext':
12195
- for c3 in c2.children:
12196
- if type(c3).__name__ == 'QualifiedNameContext':
12197
- sub_names.append(c3.getText())
12198
- if sub_names:
12199
- owned = [
12200
- {
12201
- "name": "OwnedSubsetting",
12202
- "subsettedFeature": {"name": "QualifiedName", "names": n.split("::")},
12203
- "ownedRelatedElement": []
12204
- }
12205
- for n in sub_names
12206
- ]
12296
+ # Each Owned*Context may be a dotted chain
12297
+ # (qualifiedName (DOT qualifiedName)*).
12298
+ for os_ctx in _collect_owned_contexts(
12299
+ sc.children, 'OwnedSubsettingContext',
12300
+ ('SubsetsContext', 'SpecializesContext'),
12301
+ ):
12302
+ segs = _dotted_segments(os_ctx)
12303
+ if segs:
12304
+ owned.append(_emit_owned_chain(
12305
+ 'OwnedSubsetting', 'subsettedFeature', segs))
12306
+ if owned:
12207
12307
  specialization_list.append({
12208
12308
  "name": "FeatureSpecialization",
12209
12309
  "ownedRelationship": {
@@ -12217,29 +12317,18 @@ def _build_full_specialization_from_fsp(fsp):
12217
12317
  ref_ctx = spec.references()
12218
12318
  if not isinstance(ref_ctx, list):
12219
12319
  ref_ctx = [ref_ctx]
12220
- ref_names = []
12320
+ owned = []
12221
12321
  for rc in ref_ctx:
12222
- for child in rc.children:
12223
- child_name = type(child).__name__
12224
- if child_name == 'OwnedReferenceSubsettingContext':
12225
- for c2 in child.children:
12226
- if type(c2).__name__ == 'QualifiedNameContext':
12227
- ref_names.append(c2.getText())
12228
- elif child_name == 'ReferencesContext':
12229
- for c2 in child.children:
12230
- if type(c2).__name__ == 'OwnedReferenceSubsettingContext':
12231
- for c3 in c2.children:
12232
- if type(c3).__name__ == 'QualifiedNameContext':
12233
- ref_names.append(c3.getText())
12234
- if ref_names:
12235
- owned = [
12236
- {
12237
- "name": "OwnedReferenceSubsetting",
12238
- "referencedFeature": {"name": "QualifiedName", "names": n.split("::")},
12239
- "ownedRelatedElement": []
12240
- }
12241
- for n in ref_names
12242
- ]
12322
+ # OwnedReferenceSubsettingContext may be a dotted chain.
12323
+ for ors_ctx in _collect_owned_contexts(
12324
+ rc.children, 'OwnedReferenceSubsettingContext',
12325
+ ('ReferencesContext',),
12326
+ ):
12327
+ segs = _dotted_segments(ors_ctx)
12328
+ if segs:
12329
+ owned.append(_emit_owned_chain(
12330
+ 'OwnedReferenceSubsetting', 'referencedFeature', segs))
12331
+ if owned:
12243
12332
  specialization_list.append({
12244
12333
  "name": "FeatureSpecialization",
12245
12334
  "ownedRelationship": {